Android在kts中簡單使用AIDL

Android在kts中簡單使用AIDL

AIDL相信做Android都有所了解,跨進程通信會經常使用,這里就不展開講解原理跨進程通信的方式了,最近項目換成kts的方式,于是把aidl也換成了統一的方式,其中遇到了很多問題,這里記錄一下,直接上代碼.

1.在groovy創建aidl文件:

在Groovy中是可以直接創建aidl文件的

在這里插入圖片描述

2.生成的aidl文件如下:

在這里插入圖片描述

interface IMyService {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);int add(int a, int b);
}

3.創建一個服務端Service:

MyService

package com.example.aidltestdemo;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;import androidx.annotation.Nullable;/*** @author: njb* @date: 2025/3/20 17:47* @desc: 描述*/
public class MyService extends Service {private final IMyService.Stub mBinder = new IMyService.Stub() {@Overridepublic void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {}@Overridepublic int add(int a, int b) throws RemoteException {return a + b;}};@Nullable@Overridepublic IBinder onBind(Intent intent) {return mBinder;}
}

4.注冊服務:

<serviceandroid:name=".MyService"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.example.aidltestdemo.IMyService" /></intent-filter>
</service>

在這里插入圖片描述

5.客戶端代碼:

package com.example.aidltestdemo;import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;import com.google.android.material.snackbar.Snackbar;public class MainActivity extends AppCompatActivity {private IMyService mService;private TextView textView;private static final  String TAG = "AIDlDemo";private ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mService = IMyService.Stub.asInterface(service);try {int result = mService.add(10086, 10010);Log.d(TAG,"---獲取到的數據為---: " + result);Snackbar.make(textView,"獲取到的數據為: " + result,Snackbar.LENGTH_SHORT).show();} catch (RemoteException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {mService = null;}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initService() {Intent intent = new Intent();intent.setAction("com.example.aidltestdemo.IMyService");intent.setPackage("com.example.aidltestdemo");bindService(intent, mConnection, Context.BIND_AUTO_CREATE);}private void initView() {textView = findViewById(R.id.textView);textView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {initService();}});}@Overrideprotected void onDestroy() {super.onDestroy();unbindService(mConnection);}
}

6.布局文件:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="aidl簡單測試"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

7.在kts中使用aidl:

如果是使用kts的方式默認創建aidl文件時提示沒有配置創建不了,這就和之前有很大的區別。

在這里插入圖片描述

8.在build.gradle添加配置:

在這里插入圖片描述

再次創建aidl發現按鈕是可以點擊的,配置是有效果的。

在這里插入圖片描述

9.新創建后的aidl文件:

在這里插入圖片描述

9.1 服務端代碼如下:

package com.example.aidldemo.serverimport android.app.Service
import android.content.Intent
import android.os.IBinder
import android.os.RemoteException
import com.example.aidldemo.aidl.IMyTestServer/*** @author: njb* @date: 2025/3/19 23:24* @desc: 描述*/
class MyTestService : Service() {private val mBinder: IMyTestServer.Stub = object : IMyTestServer.Stub() {@Throws(RemoteException::class)override fun basicTypes(anInt: Int,aLong: Long,aBoolean: Boolean,aFloat: Float,aDouble: Double,aString: String) {}@Throws(RemoteException::class)override fun add(a: Int, b: Int): Int {return a + b}}override fun onBind(intent: Intent): IBinder? {return mBinder}
}

9.2 注冊服務:

<service android:name=".server.MyTestService"android:process=":remote"android:enabled="true"android:exported="true">

9.3 客戶端代碼:

package com.example.aidldemo.aidlimport android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.example.aidldemo.R
import com.example.aidldemo.server.MyTestService
import com.google.android.material.snackbar.Snackbarclass MainActivity : AppCompatActivity(){private lateinit var mTvBind: TextViewprivate val TAG = MainActivity::class.java.nameprivate var testServer: IMyTestServer ?=nullprivate val mConnection: ServiceConnection = object : ServiceConnection {override fun onServiceConnected(name: ComponentName, service: IBinder) {testServer = IMyTestServer.Stub.asInterface(service)try {testServer?.let {val result: Int = it.add(188, 288)Log.d(TAG, "--結果為--: $result")Snackbar.make(mTvBind,"--獲取到的數據為--: $result",Snackbar.LENGTH_SHORT).show()}} catch (rme: RemoteException) {rme.printStackTrace()}}override fun onServiceDisconnected(name: ComponentName) {try {testServer = null} catch (e: RemoteException) {e.printStackTrace()}}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)mTvBind = findViewById(R.id.tv_bind)mTvBind.setOnClickListener{val intent = Intent(this@MainActivity,MyTestService::class.java)bindService(intent, mConnection, BIND_AUTO_CREATE)}}override fun onDestroy() {super.onDestroy()if(testServer != null && testServer!!.asBinder().isBinderAlive){testServer = null}unbindService(mConnection)}}

10.新建一個Book服務:

// ICarManager.aidl
package com.example.aidldemo.aidl;
import com.example.aidldemo.aidl.Book;
import com.example.aidldemo.aidl.IOnNewBookAddListener;
// Declare any non-default types here with import statementsinterface IBookManager {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);List<Book> getBookList();void addNewBook(in Book book);void registerListener(IOnNewBookAddListener listener);void unregisterListener(IOnNewBookAddListener listener);
}

11.新增Book列表數據接口:

// IOnNewCarAddListener.aidl
package com.example.aidldemo.aidl;
import com.example.aidldemo.aidl.Book;
// Declare any non-default types here with import statementsinterface IOnNewBookAddListener {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);void onNewBookAdd(in Book newBook);
}

12.IBook接口:

interface IBook {/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);
}

13.注冊服務:

<service android:name=".server.BookManagerService"android:process=":remote"android:enabled="true"android:exported="true">
</service>

14.客戶端Book測試代碼:

package com.example.aidldemo.aidlimport android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.os.RemoteException
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatTextView
import com.example.aidldemo.R
import com.example.aidldemo.databinding.ActivityMainBinding
import com.example.aidldemo.server.BookManagerService/*** @author: njb* @date:   2025/3/22 19:27* @desc:   描述*/
class BookTestActivity :AppCompatActivity(){private val TAG: String = "TestActivity"private var bookManager: IBookManager? = nullprivate lateinit var binding:ActivityMainBindingprivate val mConnection: ServiceConnection = object : ServiceConnection {override fun onServiceConnected(name: ComponentName, service: IBinder) {bookManager = IBookManager.Stub.asInterface(service)try {bookManager?.let {val books = it.getBookList()if (books != null && books.isNotEmpty()) {Log.d(TAG, " -- onServiceConnected -- book:$books")}it.registerListener(clientListener)}} catch (e: RemoteException) {e.printStackTrace()}}override fun onServiceDisconnected(name: ComponentName) {try {bookManager?.unregisterListener(clientListener)} catch (e: RemoteException) {e.printStackTrace()}}}private val clientListener: IOnNewBookAddListener = object : IOnNewBookAddListener.Stub() {@Throws(RemoteException::class)override fun basicTypes(anInt: Int,aLong: Long,aBoolean: Boolean,aFloat: Float,aDouble: Double,aString: String) {}@Throws(RemoteException::class)override fun onNewBookAdd(newBook: Book) {Log.d(TAG, " -- onNewBookAdd -- newBook:$newBook")}}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)binding.tvBind.setOnClickListener{val intent = Intent(this@BookTestActivity, BookManagerService::class.java)bindService(intent, mConnection, BIND_AUTO_CREATE)}binding.tvGet.setOnClickListener{try {val books = bookManager!!.bookListif (books != null && books.isNotEmpty()) {Log.d(TAG, " -- onClick -- books:$books")}} catch (e: Exception) {e.printStackTrace()}}binding.tvAdd.setOnClickListener{try {bookManager?.let {it.addNewBook(Book(1003, "計算機組成原理"))it.addNewBook(Book(1004, "操作系統"))}} catch (e: RemoteException) {e.printStackTrace()}}}override fun onDestroy() {super.onDestroy()if (bookManager != null && bookManager!!.asBinder().isBinderAlive) {try {bookManager?.unregisterListener(clientListener)} catch (e: RemoteException) {e.printStackTrace()}}unbindService(mConnection)}
}

15.普通實體類序列化:

package com.example.aidldemo.aidl;import android.os.Parcel;
import android.os.Parcelable;import androidx.annotation.NonNull;/*** @author: njb* @date: 2025/3/19 23:22* @desc: 描述*/
public class Book implements Parcelable {private int id;private String name;public Book(int id, String name){this.id = id;this.name = name;}protected Book(Parcel in) {id = in.readInt();name = in.readString();}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public static final Creator<Book> CREATOR = new Creator<Book>() {@Overridepublic Book createFromParcel(Parcel in) {return new Book(in);}@Overridepublic Book[] newArray(int size) {return new Book[size];}};@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeInt(id);dest.writeString(name);}@NonNull@Overridepublic String toString() {return String.format("[id:%d, name:%s]",id, name);}}

16.使用Parcelize序列化:

16.1 在app的build.gradle目錄添加插件配置:

plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android)id ("kotlin-parcelize")
}

在這里插入圖片描述

16.2 實體類使用Parcelize方式:

和普通的方式對比發現代碼簡潔了很多,而且使用很方便,大大減少了開發人員的工作,當然我們要搞懂其原理才能達到事半功倍的效果,要不然只是會使用,而不知道為啥這么使用及使用他的優勢和原理,對自身成長有限.

@Parcelize
data class Book(val id: Int,val name:String
):Parcelable

16.3 在libs.versions.toml添加如下插件:

jetbrains-kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }

16.4 在項目build.gradle添加配置:

plugins {alias(libs.plugins.android.application) apply falsealias(libs.plugins.jetbrains.kotlin.android) apply falsealias(libs.plugins.jetbrains.kotlin.parcelize) apply false
}

在這里插入圖片描述

16.5 在app的build.gradle配置:

plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android)alias(libs.plugins.jetbrains.kotlin.parcelize)
}

在這里插入圖片描述

17.Parcelable的優勢如下:

  • 高效性能:相比Serializable,Parcelable在序列化和反序列化過程中更加高效,因為它避免了反射的開銷。
  • 跨進程傳輸:Parcelable適用于在不同進程之間傳輸數據,例如在Android中,我們可以將Parcelable對象傳遞給另一個應用程序組件。
  • 靈活性:Parcelable允許我們選擇性地序列化對象的某些字段,而不是整個對象,這在某些情況下可以提高性能和減少傳輸的數據量。

18.遇到問題如下:

18.1 項目編譯失敗:

創建的Book服務和Book實例不在一個目錄導致編譯失敗

在這里插入圖片描述

在這里插入圖片描述

18.2 把兩個類放同一目錄編譯成功:

在這里插入圖片描述

18.3 添加Parcelize插件依賴報錯:

在這里插入圖片描述

18.4 在build.gradle.kts添加以下配置:

plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android)id ("kotlin-parcelize")
}

18.5 使用Version Catalog方式:

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
jetbrains-kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
plugins {alias(libs.plugins.android.application) apply falsealias(libs.plugins.jetbrains.kotlin.android) apply falsealias(libs.plugins.jetbrains.kotlin.parcelize) apply false
}
plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android)alias(libs.plugins.jetbrains.kotlin.parcelize)
}

19.實現的效果如下:

在這里插入圖片描述

在這里插入圖片描述

20.日志打印如下:

o                 D  Installing profile for com.example.aidldemo
2025-03-23 20:26:39.912  4722-4722  TestActivity            com.example.aidldemo                 D   -- onServiceConnected -- book:[Book(id=1001, name=Java入門到精通)]
---------------------------- PROCESS STARTED (4797) for package com.example.aidldemo ----------------------------
2025-03-23 20:26:42.911  4722-4741  TestActivity            com.example.aidldemo                 D   -- onNewBookAdd -- newBook:Book(id=1002, name=C++程序設計)
2025-03-23 20:27:24.033  4722-4722  TestActivity            com.example.aidldemo                 D   -- onClick -- books:[Book(id=1001, name=Java入門到精通), Book(id=1002, name=C++程序設計)]
2025-03-23 20:27:39.776  4722-4722  TestActivity            com.example.aidldemo                 D   -- onNewBookAdd -- newBook:Book(id=1003, name=計算機組成原理)
2025-03-23 20:27:39.777  4722-4722  TestActivity            com.example.aidldemo                 D   -- onNewBookAdd -- newBook:Book(id=1004, name=操作系統)

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

21.總結:

  • 使用kts的方式需要先使用buildFeatures配置aidl.
  • 使用Parcelize序列化數據很簡單方便.
  • 要注意創建aidl文件的目錄和包名這些在同一目錄.
  • 使用Version Catalog方式要主要依賴配置的方式.
  • 感興趣的小伙伴可以自己嘗試一下,后面會講解aidl如何傳輸大文件.

22.源碼如下:

https://gitee.com/jackning_admin/aidl-test-demo

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/898816.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/898816.shtml
英文地址,請注明出處:http://en.pswp.cn/news/898816.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

論文閱讀:2024-NAACL Semstamp、2024-ACL (Findings) k-SemStamp

總目錄 大模型安全相關研究:https://blog.csdn.net/WhiffeYF/article/details/142132328 Semstamp: A semantic watermark with paraphrastic robustness for text generation https://aclanthology.org/2024.naacl-long.226/ k-SemStamp: A Clustering-Based Semantic Wate…

物化視圖詳解:數據庫性能優化的利器

物化視圖&#xff08;Materialized View&#xff09;作為數據庫性能優化的核心手段&#xff0c;通過預計算和存儲查詢結果&#xff0c;顯著提升了復雜查詢的效率。本文將深入剖析物化視圖的工作原理、應用場景及最佳實踐&#xff0c;幫助企業在合適的場景中充分發揮其性能優勢。…

快速入手:Nacos融合SpringCloud成為注冊配置中心

快速入手&#xff1a;Nacos融合SpringCloud成為注冊配置中心 前言安裝Nacos項目搭建添加配置啟動類添加注解運行項目服務調用RestTemplate 模式FeignClient 模式 Gateway 網關 前言 Spring Cloud是一系列框架的集合&#xff0c;提供了微服務架構下的各種解決方案&#xff0c;如…

2025年2月-3月后端go開發找工作感悟

整體感悟 目標 找工作首先要有一個目標&#xff0c;這個目標盡可能的明確&#xff0c;比如我要字節、拼多多之類的公司&#xff0c;還是要去百度、滴滴這樣的&#xff0c;或者目標是創業公司。但是這個目標是會動態調整的&#xff0c;有可能我們的心態發生了變化&#xff0c;一…

Python | 如何在Pandas中刪除常量列

在數據分析中&#xff0c;經常會遇到數據集中始終具有常量值的列&#xff08;即&#xff0c;該列中的所有行包含相同的值&#xff09;。這樣的常量列不提供有意義的信息&#xff0c;可以安全地刪除而不影響分析。 如&#xff1a; 在本文中&#xff0c;我們將探索如何使用Pyth…

5.高頻加熱的原理與常用集成電路介紹

一、高頻加熱的類型 利用高頻電源加熱通常由兩種方法&#xff1a;電介質加熱&#xff08;被加熱物體絕緣&#xff09;與感應加熱&#xff08;被加熱物體導電&#xff09;&#xff0c;詳細解釋如下&#xff1a; 電介質加熱&#xff08;利用高頻電壓的高頻電場導致物體自身分子摩…

串口通信與Modbus通信的區別和聯系

一、定義與定位 1?、串口通信? 是物理層的硬件接口標準&#xff0c;用于實現設備間的?串行數據傳輸?&#xff0c;常見類型包括RS-232、RS-485和RS-422?35。其功能是完成并行數據與串行信號的轉換&#xff0c;并定義電氣特性&#xff08;如電平、傳輸速率&#xff09;?。…

Linux生產者消費者模型

Linux生產者消費者模型 Linux生產者消費者模型詳解生產者消費者模型生產者消費者模型的概念生產者消費者模型的特點生產者消費者模型優點 基于BlockingQueue的生產者消費者模型基于阻塞隊列的生產者消費者模型模擬實現基于阻塞隊列的生產消費模型基礎實現生產者消費者步調調整條…

【中文翻譯】第9章-The Algorithmic Foundations of Differential Privacy

由于GitHub項目僅翻譯到前5章&#xff0c;我們從第6章開始通過大語言模型翻譯&#xff0c;并導出markdown格式。 大模型難免存在錯漏&#xff0c;請讀者指正。 教材原文地址&#xff1a;https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf 9 差分隱私與計算復雜度 到目…

【AI大模型】搭建本地大模型GPT-NeoX:詳細步驟及常見問題處理

搭建本地大模型GPT-NeoX:詳細步驟及常見問題處理 GPT-NeoX是一個開源的大型語言模型框架,由EleutherAI開發,可用于訓練和部署類似GPT-3的大型語言模型。本指南將詳細介紹如何在本地環境中搭建GPT-NeoX,并解決過程中可能遇到的常見問題。 1. 系統要求 1.1 硬件要求 1.2 軟…

Unity跨平臺構建快速回顧

知識點來源&#xff1a;人間自有韜哥在&#xff0c;豆包 目錄 一、發布應用程序1. 修改發布必備設置1.1 打開設置面板1.2 修改公司名、游戲項目名、版本號和默認圖標1.3 修改 Package Name 和 Minimum API Level 2. 發布應用程序2.1 配置 Build Settings2.2 選擇發布選項2.3 構…

低配電腦暢玩《怪物獵人:荒野》,ToDesk云電腦優化從30幀到144幀?

《怪物獵人&#xff1a;荒野&#xff08;Monster Hunter Wilds&#xff09;》自2025年正式發售以來已取得相當亮眼的成績&#xff0c;僅用三天時間便輕松突破800萬銷量&#xff0c;目前順利蟬聯周榜冠軍&#xff1b;憑借著開放世界的宏大場景和豐富的狩獵玩法&#xff0c;該游戲…

Flink基礎簡介和安裝部署

文章目錄 一、Flink基礎簡介1、什么是Flink2、Flink流處理特性3、Flink四大基石4、Flink中的角色 二、Flink集群搭建1、Local模式①上傳Flink安裝包②啟動交互窗口③提交任務測試④訪問WebUI頁面查看④退出停止集群 一、Flink基礎簡介 1、什么是Flink Flink是?個分布式&#…

【2025】基于ssm+jsp的二手商城系統設計與實現(源碼、萬字文檔、圖文修改、調試答疑)

基于SSMJSP的二手商城系統設計與實現系統功能結構圖&#xff1a; 課題背景 隨著經濟的發展和人們生活水平的提高&#xff0c;二手交易市場日益活躍。人們對于閑置物品的處理方式逐漸從傳統的廢品回收轉變為通過二手交易平臺進行再利用。這種交易模式不僅能夠幫助用戶節省開支&a…

幻影星空亮相CAAPA北京展 引領文旅產業升級轉型

3月19日&#xff0c;中國游藝機游樂園協會&#xff08;CAAPA&#xff09;主辦的2025中國&#xff08;北京&#xff09;國際游樂設施設備博覽會及2025北京國際旅游休閑娛樂產業博覽會在北京盛大啟幕。在這場行業盛會上&#xff0c;廣州卓遠旗下的“幻影星空”品牌以創新性的虛擬…

銀河麒麟桌面版包管理器(二)

以下內容摘自《銀河麒麟操作系統進階應用》一書 APT包管理器 APT是Debian及其派生系統的包管理器&#xff0c;構建在dpkg之上&#xff0c;以其強大的依賴性處理能力和豐富的軟件倉庫而聞名。APT具有自動解決依賴關系、提供易于使用的命令行工具&#xff08;如apt-get、apt-ca…

【STM32實物】基于STM32的掃地機器人/小車控制系統設計

基于STM32的掃地機器人/小車控制系統設計 演示視頻: 基于STM32的掃地機器人小車控制系統設計 簡介:掃地機器人系統采用分層結構設計,主要包括底層硬件控制層、中間數據處理層和上層用戶交互層。底層硬件控制層負責對各個硬件模塊進行控制和數據采集,中間數據處理層負責對采…

STM32收發數據包中間件——ProtoFlow,更方便的打包解包助手

引言 在嵌入式開發中&#xff0c;數據包封裝是不可或缺的一環。手動編寫協議不僅耗時&#xff0c;還容易出錯。ProtoFlow 的出現&#xff0c;就是為了讓數據包封裝變得簡單、高效、可靠。它不僅占用資源少&#xff0c;還能適配多種場景&#xff0c;是你項目的理想助手。 項目地…

Xcode16.1使用MonkeyDev運行Tiktok報錯分析

問題1&#xff1a; Build input files cannot be found: /usr/lib/libc.dylib, /usr/lib/libstdc.dylib. Did you forget to declare these files as outputs of any script phases or custom build rules which produce them? 解決辦法&#xff1a;在TARGETS的dylib中的Bui…

R語言交互項-formula

R語言交互項-formula 交互項的模型交互項的幾種情形連續變量和連續變量連續變量和分類變量分類變量和分類變量總結交互項的模型 統計中的交互和相關是完全不同的兩個概念,交互項是指兩個或者多個變量對因變量的協同效應,關注變量對因變量的聯合影響,比如變量X對Y的影響是否因…