android 实现aidl跨进程通信之二

xiaoxiao2021-02-28  104

2,aidl回调

上面服务端ExampleService.java类做了简单的回调,存在很多bug,其实android系统已经包装了aidl的回调,使用了RemoteCallbackList.java类。

重新修改的服务端ExampleService.java如下,

package com.android.exampleservice; import android.app.Service; import android.os.Bundle; import android.content.Intent; import android.os.IBinder; import android.util.Log; import android.os.Handler; import android.os.Message; import android.os.RemoteException; import android.os.RemoteCallbackList; import com.android.aidl.IObdData; import com.android.aidl.ICallback; public class ExampleService extends Service { private static String TAG = "ExampleService "; private ICallback mICallback; private final RemoteCallbackList<ICallback> mRemoteCallbacks = new RemoteCallbackList<ICallback>(); @Override public void onCreate() { Log.d(TAG,"ExampleService: onCreate "); } private IObdData.Stub mDataBinder = new IObdData.Stub() { @Override public String getData(String sr){ Log.d(TAG,"IObdData: getData " + sr); return sr + "getData "; } @Override public void sendMessage(String sr, ICallback mcallback){ Log.d(TAG,"IObdData: sendMessage " + sr); mICallback = mcallback; if (mcallback != null) { mICallback = mcallback; mRemoteCallbacks.register(mcallback); } Message msg = mHandler.obtainMessage(); msg.what = OUT_SEND; mHandler.sendMessageDelayed(msg,5000); } }; public static final int OUT_SEND = 10; public final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case OUT_SEND: getResult("sendMessage success"); break; } } }; private void getResult(String sa) { final int N = mRemoteCallbacks.beginBroadcast(); for (int i = 0; i < N; i++) { try { mRemoteCallbacks.getBroadcastItem(i).onGetResult(sa); } catch (RemoteException e) { e.printStackTrace(); } } mRemoteCallbacks.finishBroadcast(); mRemoteCallbacks.unregister(mICallback); } @Override public IBinder onBind(Intent intent) { return mDataBinder; } }

主要代码如下,

mRemoteCallbacks.register(mcallback); private void getResult(String sa) { final int N = mRemoteCallbacks.beginBroadcast(); for (int i = 0; i < N; i++) { try { mRemoteCallbacks.getBroadcastItem(i).onGetResult(sa); } catch (RemoteException e) { e.printStackTrace(); } } mRemoteCallbacks.finishBroadcast(); mRemoteCallbacks.unregister(mICallback); }

3, linkToDeath机制

服务端和客户端已经绑定了,当一个进程被kill的时候,另外一个进程是如何知道的呢?

这就要使用到Ibinder的内部接口DeathRecipient了,该接口只有一个binderDied方法。

3.1服务端kill

服务端ExampleService进程kill了,客户端ExampleActivity进程如何知道呢?

在ExampleActivity的onServiceConnected中添加,

@Override public void onServiceConnected(ComponentName name, IBinder service) { try { service.linkToDeath(deathHandle, 0); } catch (RemoteException e) { e.printStackTrace(); } •••

deathHandle是一个匿名DeathRecipient对象,

final DeathRecipient deathHandle = new DeathRecipient() { @Override public void binderDied() { Log.d(TAG, "binder is died"); } };

这样当服务端进程kill时,会回调客户端的binderDied方法。

 

例如,在ExampleService.java的onBind方法中手动将服务端的进程杀死。

@Override public IBinder onBind(Intent intent) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } android.os.Process.killProcess(android.os.Process.myPid()); Log.d(TAG, "stopSelf"); //stopSelf();// 仅仅终止服务还是不行的,必须杀死进程。 } }).start(); return mDataBinder; }

服务端启动10s之后,就会杀死进程,然后客户端就会调用binderDied方法。

 

3.2客户端kill

客户端进程kill时,服务端是如何知道呢?

在3.1小节中,客户端持有服务端的Ibinder对象,在onServiceConnected方法中,然后才可以调用linkToDeath方法。

服务端如果想知道客户端进程何时kill,也必须持有客户端的Ibinder对象。

思路:在客户端将Ibinder对象通过aidl传到客户端。

1,在IObdData.aidl文件中添加一个方法,

void setBinder(IBinder mIBinder);

2,在客户端ExampleActivity.java获取Ibinder对象,调用setBinder方法。

private IBinder mBinder = new Binder();

在onServiceConnected中的try模块中添加,

mObdData.setBinder(mBinder);

3,在服务端ExampleService.java的IObdData.Stub中实现setBinder方法,

@Override public void setBinder(IBinder mIBinder) throws RemoteException { mClient = mIBinder; mClient.linkToDeath(deathHandle, 0); }

匿名DeathRecipient对象如下,

final DeathRecipient deathHandle = new DeathRecipient() { @Override public void binderDied() { Log.d(TAG, "binder is died"); } };

例如,在客户端绑定后,客户端进程杀死自己,服务端就会调用binderDied方法。

在客户端的ExampleActivity启动之后10s中杀死进程。

new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } android.os.Process.killProcess(android.os.Process.myPid()); } }).start();
转载请注明原文地址: https://www.6miu.com/read-63745.html

最新回复(0)