Android 跨程序通訊之AIDL
阿新 • • 發佈:2022-05-25
前言
在Android跨程序通訊的方式有很多比如廣播,ContentProvider,AIDL等等,它們各自有各自的使用範圍。而且AIDL更像是Java的ServerSocket通訊機制, 需要一個常駐的服務端與呼叫它的客戶端。AIDL現在的缺點可能也是需要一個服務配合使用。因為目前Android端Server的使用要求越來越多(前臺化),使用場景也越來越少(WorkManager替代),所有
簡單實現Demo
服務端
建立AIDL
建立
完成後,在這個預設檔案裡會有一些預設方法,它告訴你了AIDL可以使用那些型別資料
編輯AIDL檔案
編輯完成後,ReBuild 重新編譯下整個專案,Android stuido會自動在debug裡生成一份對應的aidl的java介面類
package com.zh.aidl; interface IDemoService { void setNum(int num); int getNum(); }
自動生成的java介面
建立服務,將服務繫結AIDL
註冊清單
<!-- android:enabled="true" 與 android:exported="true" 是必要屬性 --> <!-- android:enabled 定義服務能否被系統例項化的標籤,true表示可以例項化,false不能例項化,預設為true。標籤也有enabled標籤,這個標籤適用於application下所有元件。 只有當和下enabled標籤的屬性都為true的時候,才可以將廣播接受者啟動(enabled),否則廣播接受者不能開啟(disabled),不能被例項化。--> <!-- android:exported 定義服務能否被外部應用的元件呼叫或者互動,true表示可以,false表示不能。 如果設定為false,服務只能接收本應用的元件或者是具有相同使用者ID的應用所發出的所開啟或繫結。 --> <service android:name=".DemoService" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="DemoService" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service> </application>
服務
import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.graphics.BitmapFactory; import android.graphics.Color; import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; public class DemoService extends Service { private static final String CHANNEL_ID = "DemoService"; private int mNum = 0; @Nullable @Override public IBinder onBind(Intent intent) { //繫結AIDL return iBinder; } /** * 例項化AIDL */ private IBinder iBinder = new IDemoService.Stub() { @Override public void setNum(int num) throws RemoteException { mNum = num; Log.e("zh", "伺服器端接收資料: Num = " + num); } @Override public int getNum() throws RemoteException { return mNum; } }; @Override public void onCreate() { super.onCreate(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { frontDeskService(); } } /** * 前臺服務 */ @RequiresApi(api = Build.VERSION_CODES.O) private void frontDeskService() { NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "主服務", NotificationManager.IMPORTANCE_HIGH); channel.enableLights(true);//設定提示燈 channel.setLightColor(Color.RED);//設定提示燈顏色 channel.setShowBadge(true);//顯示logo channel.setDescription("zh");//設定描述 channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); //設定鎖屏可見 VISIBILITY_PUBLIC=可見 manager.createNotificationChannel(channel); Notification notification = new Notification.Builder(this) .setChannelId(CHANNEL_ID) .setContentTitle("主服務")//標題 .setContentText("執行中...")//內容 .setWhen(System.currentTimeMillis()) .setSmallIcon(R.mipmap.ic_launcher)//小圖示一定需要設定,否則會報錯(如果不設定它啟動服務前臺化不會報錯,但是你會發現這個通知不會啟動),如果是普通通知,不設定必然報錯 .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) .build(); startForeground(1, notification); } }
啟動服務
private fun startService() { val intent = Intent(this, DemoService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(intent) } else{ startService(intent) } }
客戶端
將服務端的AIDL檔案複製到客戶端裡,注意包名路徑要一致
繫結服務,接收資料,傳送資料
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(mBinding.root) mBinding.connectService.setOnClickListener { //繫結服務 val intent = Intent().apply { setPackage("com.zh.aidl") setAction("DemoService") } bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE) } mBinding.sendValue.setOnClickListener { //傳送資料 mIDemoService?.num = mBinding.editTextNumber.text.toString().toInt() } mBinding.getValue.setOnClickListener { //接收資料 Log.e("zh", "客戶端接收: num = " + mIDemoService?.num) } }
End