前言:
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(); } }
-
运行效果
源码下载地址