上一小节我们添加了一个 java service,也写了一个 client 来做测试。但只是单向的从 client 调用 service,实际项目中我们经常是需要双向调用的。某些事件发生的时候,service 端需要通知 client 来处理。这节我们就来学习一下如何从 service 端回调 client。为了简单起见,我们直接在上一小节的代码基础上进行修改。
1. 使用 aidl 定义callback接口
在 frameworks/base/core/java/android/pure 目录下创建 ICallback.aidl
| 12
 3
 4
 
 | package android.pure;interface ICallback {
 void onMessage(in String message);
 }
 
 | 
在 frameworks/base/Android.bp framework-defaults 模块中添加我们刚刚加的 aidl 文件
| 1
 | "core/java/android/pure/ICallback.aidl",
 | 
然后进入 framework/base 目录执行 mm -j 命令编译 framework.jar 模块。
编译成功后,会在 out/soong/.intermediates/frameworks/base/framework/android_common/gen/aidl/frameworks/base/core/java/android/pure 目录生成 ICallback.java 这个文件。
2. 添加注册回调接口
修改 IHelloService.aidl 如下
| 12
 3
 4
 5
 6
 7
 
 | package android.pure;import android.pure.ICallback;
 interface IHelloService {
 void hello(in String name);
 void registerCallback(in int pid, in ICallback callback);
 void unregisterCallback(in int pid);
 }
 
 | 
HelloService.java 修改如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 
 | package com.android.server;
 import android.os.RemoteException;
 import android.pure.IHelloService;
 import android.pure.ICallback;
 import android.util.Log;
 
 import java.util.HashMap;
 import java.util.Map;
 
 public class HelloService extends IHelloService.Stub {
 private final String TAG = "HelloService";
 private Map<Integer, ICallback> mClients;
 
 public HelloService() {
 Log.d(TAG, "create hello service");
 mClients = new HashMap<>();
 }
 
 @Override
 public void hello(String name) {
 Log.d(TAG, "hello " + name);
 try {
 for (ICallback callback : mClients.values()) {
 callback.onMessage("message from service");
 }
 } catch (RemoteException e) {
 e.printStackTrace();
 }
 }
 
 @Override
 public void registerCallback(int pid, ICallback callback) {
 mClients.put(pid, callback);
 Log.d(TAG, "registerCallback client's size = " + mClients.size());
 }
 
 @Override
 public void unregisterCallback(int pid) {
 mClients.remove(pid);
 Log.d(TAG, "unregisterCallback client's size = " + mClients.size());
 }
 }
 
 | 
我们把 client 传递过来的 callback 保存到 mClients 集合中,当 client 调用 hello 接口时, 遍历 mclients 把消息传递给 client。
3. client 注册回调接口
修改 PureSettings apk 中的 MainActivity
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 
 | package com.pure.settings;
 import android.app.Activity;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.pure.ICallback;
 import android.pure.IHelloService;
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
 
 public class MainActivity extends Activity {
 
 private static final String TAG = "PureSettings";
 private IHelloService service = null;
 
 private Button button;
 
 private ICallback callback = new ICallback.Stub() {
 
 @Override
 public void onMessage(String message) throws RemoteException {
 Log.d(TAG, "onMessage:" + message);
 }
 };
 
 private void test() {
 Log.d(TAG, "test");
 try {
 service.hello("qiushao");
 } catch (RemoteException e) {
 e.printStackTrace();
 }
 }
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 service = IHelloService.Stub.asInterface(ServiceManager.getService("HelloService"));
 button = (Button) findViewById(R.id.button);
 button.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 test();
 }
 });
 }
 
 @Override
 protected void onResume() {
 super.onResume();
 try {
 service.registerCallback(android.os.Process.myPid(), callback);
 } catch (RemoteException e) {
 e.printStackTrace();
 }
 }
 
 @Override
 protected void onStop() {
 super.onStop();
 try {
 service.unregisterCallback(android.os.Process.myPid());
 } catch (RemoteException e) {
 e.printStackTrace();
 }
 }
 }
 
 | 
4. 编译验证
整编系统,运行虚拟机,打开 PureSettings 测试,查看 logcat
| 12
 3
 4
 5
 6
 7
 
 | pure:/ # logcat -s HelloService:D PureSettings:D02-02 22:57:37.913  1769  1769 D HelloService: create hello service
 02-02 22:57:53.498  1769  3058 D HelloService: registerCallback client's size = 1
 02-02 22:57:56.587  3580  3580 D PureSettings: test
 02-02 22:57:56.587  1769  3058 D HelloService: hello qiushao
 02-02 22:57:56.588  3580  3580 D PureSettings: onMessage:message from service
 02-02 22:58:01.160  1769  3503 D HelloService: unregisterCallback client's size = 0
 
 | 
从 log 上看,client 收到了 service 传递过来的消息。