AIDL:Android Interface Definition Language,翻译过来就是Android接口定义语言。是用于定义服务器和客户端通信接口的一种描述语言,可以拿来生成用于IPC的代码。所以使用AIDL需要一个服务端和客户端
作用:可以在一个进程中获取另一个进程的数据和调用其暴露出来的方法,从而满足进程间通信的需求。
import com.pgc.testaidldemo1.IAidlCallBack;
interface IAidlInterface {
void registerCallBack(IAidlCallBack iAidlCallBack);
void unregisterCallBack(IAidlCallBack iAidlCallBack);
void sendMessage(String message);
List getMessages();
}
编写IAidlCallBack.aidl代码:既然是回调接口,那么我们只需要一个消息发送成功的回调接口就行,代码如下
interface IAidlCallBack {
void onMessageSuccess(String message);
}
既然是服务端,我们需要实现接收消息已经处理消息的逻辑代码,所以我们创建一个AidlService,继承Service,因为Service不能直接接收Callback,但是提供了RemoteCallbackList来注册回调
private RemoteCallbackList 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 getMessages() throws RemoteException {
return messages;
}
};
在AndroidManifest.xml注册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;
@SuppressLint("Registered")
public class AidlService extends Service {
private RemoteCallbackList callbackList= new RemoteCallbackList();
private List 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 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 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 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();
}
}
运行效果
源码下载地址
https://github.com/pengkongkong/TestAidlDemo1作者:养猫误码