前言:
AIDL:Android Interface Definition Language,翻譯過來就是Android接口定義語言。是用於定義服務器和客戶端通信接口的一種描述語言,可以拿來生成用於IPC的代碼。所以使用AIDL需要一個服務端和客戶端
作用:可以在一個進程中獲取另一個進程的數據和調用其暴露出來的方法,從而滿足進程間通信的需求。
1.AIDL支持的基本數據類型
- 八種基本數據類型:byte、char、short、int、long、float、double、boolean
- String,CharSequence
- 實現了Parcelable接口的數據類型
- List 類型。List承載的數據必須是AIDL支持的類型,或者是其它聲明的AIDL對象
- Map類型。Map承載的數據必須是AIDL支持的類型,或者是其它聲明的AIDL對象
2.服務端的實現
創建工程,以及所需aidl文件
- 使用Android Studio新建一個工程,命名爲TestAidlDemo1
- 右鍵New一個AIDL文件,取名爲IAidlInterface,AS會自動在工程目錄生成一個路徑完全一樣的aidl文件夾
- 既然是要回調消息,那就還需要一個回調接口,同樣的方法,創建IAidlCallBack.aidl文件,那麼接下來就進行代碼編寫
實現代碼邏輯
- 編寫IAidlInterface.aldi代碼,因爲我們需要回調消息,那麼我們需要註冊回調以及註銷回調接口,一個發送消息的接口,一個獲取歷史消息的接口,代碼如下(AIDL文件不會自動導包,一些不是基本支持數據類型需要我們自己手動import,)
import com.pgc.testaidldemo1.IAidlCallBack; interface IAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void registerCallBack(IAidlCallBack iAidlCallBack); void unregisterCallBack(IAidlCallBack iAidlCallBack); void sendMessage(String message); List<String> getMessages(); }
-
編寫IAidlCallBack.aidl代碼:既然是回調接口,那麼我們只需要一個消息發送成功的回調接口就行,代碼如下
interface IAidlCallBack { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void onMessageSuccess(String message); }
-
既然是服務端,我們需要實現接收消息已經處理消息的邏輯代碼,所以我們創建一個AidlService,繼承Service,因爲Service不能直接接收Callback,但是提供了RemoteCallbackList來註冊回調
private RemoteCallbackList<IAidlCallBack> callbackList= new RemoteCallbackList<>();
同時RemoteCallbackList提供了beginBroadcast來獲取當前註冊的回調數,因此我們可以通過這個方法進行回調處理(再使用了beginBroadcast之後必須調用finishBroadcast不然會報beginBroadcast() called while already in a broadcast錯誤)
final int num=callbackList.beginBroadcast(); for (int i=0;i<num;i++){ IAidlCallBack iAidlCallBack=callbackList.getBroadcastItem(i); iAidlCallBack.onMessageSuccess(message); } callbackList.finishBroadcast();
接下來實例化binder對象並返回給客戶端,
@Override public IBinder onBind(Intent intent) { return binder; } private final IAidlInterface.Stub binder=new IAidlInterface.Stub() { @Override public void registerCallBack(IAidlCallBack iAidlCallBack) throws RemoteException { callbackList.register(iAidlCallBack); } @Override public void unregisterCallBack(IAidlCallBack iAidlCallBack) throws RemoteException { callbackList.unregister(iAidlCallBack); } @Override public void sendMessage(String message) throws RemoteException { messages.add(message); final int num=callbackList.beginBroadcast(); for (int i=0;i<num;i++){ IAidlCallBack iAidlCallBack=callbackList.getBroadcastItem(i); iAidlCallBack.onMessageSuccess(message); } callbackList.finishBroadcast(); } @Override public List<String> getMessages() throws RemoteException { return messages; } };
-
在AndroidManifest.xml註冊Service
<service android:name=".AidlService" android:enabled="true" android:exported="true" > <intent-filter android:priority="1000"> <action android:name="AIDL.service"></action> </intent-filter> </service>
-
AidlService全部代碼
package com.pgc.testaidldemo1; import android.annotation.SuppressLint; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import androidx.annotation.Nullable; import java.util.ArrayList; import java.util.List; /** * Created by PengGuiChu on 2020/4/11. */ @SuppressLint("Registered") public class AidlService extends Service { private RemoteCallbackList<IAidlCallBack> callbackList= new RemoteCallbackList<>(); private List<String> messages=new ArrayList<>(); @Nullable @Override public IBinder onBind(Intent intent) { return binder; } private final IAidlInterface.Stub binder=new IAidlInterface.Stub() { @Override public void registerCallBack(IAidlCallBack iAidlCallBack) throws RemoteException { callbackList.register(iAidlCallBack); } @Override public void unregisterCallBack(IAidlCallBack iAidlCallBack) throws RemoteException { callbackList.unregister(iAidlCallBack); } @Override public void sendMessage(String message) throws RemoteException { messages.add(message); final int num=callbackList.beginBroadcast(); for (int i=0;i<num;i++){ IAidlCallBack iAidlCallBack=callbackList.getBroadcastItem(i); iAidlCallBack.onMessageSuccess(message); } callbackList.finishBroadcast(); } @Override public List<String> getMessages() throws RemoteException { return messages; } }; @Override public void onCreate() { super.onCreate(); } }
-
因爲是服務端和客戶端實現相互消息回調,因此在服務端也需要通過binderService來獲取binder,相對客戶端,因爲服務端和AidlService是在同一線程,我們可以直接binderService
Intent intent=new Intent(getApplicationContext(),AidlService.class); bindService(intent,serviceConnection,BIND_AUTO_CREATE);
然後實例化ServiceConnection
private ServiceConnection serviceConnection=new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { } @Override public void onServiceDisconnected(ComponentName componentName) { } };
然後在onServiceConnected中獲取binder
iAidlInterface=IAidlInterface.Stub.asInterface(iBinder); try { iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);//監聽進程是否消失 iAidlInterface.registerCallBack(iAidlCallBack);//註冊消息回調 messages.addAll(iAidlInterface.getMessages());//獲取歷史消息 listView.setAdapter(arrayAdapter=new ArrayAdapter<> (getApplicationContext(),android.R.layout.simple_list_item_1,messages)); } catch (RemoteException e) { e.printStackTrace(); }
DeathRecipient實例
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { //當承載IBinder的進程消失時接收回調的接口 @Override public void binderDied() { if (null == iAidlInterface) { return; } try { iAidlInterface.unregisterCallBack(iAidlCallBack);//註銷 } catch (RemoteException e) { e.printStackTrace(); } iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0); iAidlInterface = null; } };
iAidlCallBack實例
private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() { @Override public void onMessageSuccess(String message) { if (messages!=null&&arrayAdapter!=null){ messages.add(message); handler.sendEmptyMessage(1); } } };
MainActivity全部代碼
package com.pgc.testaidldemo1; import android.annotation.SuppressLint; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import java.util.ArrayList; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; public class MainActivity extends AppCompatActivity { @BindView(R.id.list_view) ListView listView; private IAidlInterface iAidlInterface; private int num; private List<String> messages=new ArrayList<>(); private ArrayAdapter arrayAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); Intent intent=new Intent(getApplicationContext(),AidlService.class); bindService(intent,serviceConnection,BIND_AUTO_CREATE); } @OnClick(R.id.send_message) public void onViewClicked(View view) { if (iAidlInterface!=null){ try { iAidlInterface.sendMessage("消息"+num); num++; } catch (RemoteException e) { e.printStackTrace(); } } } private ServiceConnection serviceConnection=new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { iAidlInterface=IAidlInterface.Stub.asInterface(iBinder); try { iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);//監聽進程是否消失 iAidlInterface.registerCallBack(iAidlCallBack);//註冊消息回調 messages.addAll(iAidlInterface.getMessages());//獲取歷史消息 listView.setAdapter(arrayAdapter=new ArrayAdapter<>(getApplicationContext(),android.R.layout.simple_list_item_1,messages)); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName componentName) { } }; private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { //當承載IBinder的進程消失時接收回調的接口 @Override public void binderDied() { if (null == iAidlInterface) { return; } try { iAidlInterface.unregisterCallBack(iAidlCallBack);//註銷 } catch (RemoteException e) { e.printStackTrace(); } iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0); iAidlInterface = null; } }; private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() { @Override public void onMessageSuccess(String message) { if (messages!=null&&arrayAdapter!=null){ messages.add(message); handler.sendEmptyMessage(1); } } }; @SuppressLint("HandlerLeak") private Handler handler=new Handler(){ @Override public void handleMessage(@NonNull Message msg) { arrayAdapter.notifyDataSetChanged(); } }; @Override protected void onDestroy() { //解除註冊 if (null != iAidlInterface && iAidlInterface.asBinder().isBinderAlive()) { try { iAidlInterface.unregisterCallBack(iAidlCallBack); } catch (RemoteException e) { e.printStackTrace(); } } //解除綁定服務 unbindService(serviceConnection); super.onDestroy(); } }
到此我們的服務端就編碼完成,實現效果
3.客戶端實現
創建client工程
- 選中TestAidlDemo1工程右鍵NEW一個model,命名爲client
- 要想client項目能夠連接上Service,我們直接複製上面工程的aidl文件到client工程的main文件裏,這樣是爲了保證兩個項目的aidl文件路徑一致
- 而調用邏輯基本和上面MainActivity一樣,需要注意一點的是,因爲是兩個不同進程,在這裏我們不能直接bindService來調起服務端,而是通過以下代碼實現
Intent intent=new Intent(); String ACTION = "AIDL.service";//對應服務端AndroidManifest.xml配置service action:name intent.setAction(ACTION); intent.setPackage("com.pgc.testaidldemo1");//對應服務端AndroidManifest.xml package bindService(intent,serviceConnection,BIND_AUTO_CREATE);
-
client的MainActivity全部代碼
package com.pgc.client; import android.annotation.SuppressLint; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.pgc.testaidldemo1.IAidlCallBack; import com.pgc.testaidldemo1.IAidlInterface; import java.util.ArrayList; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; public class MainActivity extends AppCompatActivity { @BindView(R.id.list_view) ListView listView; private IAidlInterface iAidlInterface; private int num; private List<String> messages=new ArrayList<>(); private ArrayAdapter arrayAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); Intent intent=new Intent(); String ACTION = "AIDL.service"; intent.setAction(ACTION); intent.setPackage("com.pgc.testaidldemo1"); bindService(intent,serviceConnection,BIND_AUTO_CREATE); } @OnClick(R.id.send_message) public void onViewClicked(View view) { if (iAidlInterface!=null){ try { iAidlInterface.sendMessage("消息"+num); num++; } catch (RemoteException e) { e.printStackTrace(); } } } private ServiceConnection serviceConnection=new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { iAidlInterface=IAidlInterface.Stub.asInterface(iBinder); try { iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0); iAidlInterface.registerCallBack(iAidlCallBack); messages.addAll(iAidlInterface.getMessages()); listView.setAdapter(arrayAdapter=new ArrayAdapter<>(getApplicationContext(),android.R.layout.simple_list_item_1,messages)); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName componentName) { } }; private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { //當承載IBinder的進程消失時接收回調的接口 @Override public void binderDied() { if (null == iAidlInterface) { return; } iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0); iAidlInterface = null; //斷線重來邏輯 } }; private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() { @Override public void onMessageSuccess(String message) { if (messages!=null&&arrayAdapter!=null){ messages.add(message); handler.sendEmptyMessage(1); } } }; @SuppressLint("HandlerLeak") private Handler handler=new Handler(){ @Override public void handleMessage(@NonNull Message msg) { arrayAdapter.notifyDataSetChanged(); } }; @Override protected void onDestroy() { //解除註冊 if (null != iAidlInterface && iAidlInterface.asBinder().isBinderAlive()) { try { iAidlInterface.unregisterCallBack(iAidlCallBack); } catch (RemoteException e) { e.printStackTrace(); } } //解除綁定服務 unbindService(serviceConnection); super.onDestroy(); } }
-
運行效果
源碼下載地址