本文在Binder 程序示例之 Java 篇 的基础上修改,来显示如何添加 Java 系统服务回调,为了保证重点突出和过程简洁清晰,不会演示如何集成 Java 系统服务到系统中。这部分内容请参考添加 Java 系统服务和Android Java 系统服务框架与第三方 App 使用自定义 Java 系统服务。
首先我们在Binder 程序示例之 Java 篇完成的源码的基础上添加 ICallback.aidl 文件,添加完成后整体文件结构如下:
bash
BinderJavaDemo/
└── com
└── yuandaima
├── Android.bp
├── Client.java
├── HelloService.java
├── ICallback.aidl
├── IHelloService.aidl
└── Server.java
其中 ICallback.aidl 内容如下:
java
package com.yuandaima;
interface ICallback {
void onMessage(String message);
}
接着修改 IHelloService.aidl 添加服务注册接口:
java
package com.yuandaima;
import com.yuandaima.ICallback;
interface IHelloService
{
void sayhello();
int sayhello_to(String name);
void registerCallback(int pid, ICallback callback);
}
接下里我们编译 aidl 文件:
bash
source build/envsetup.sh
# 选择合适的 product
lunch
aidl ICallback.aidl
# -I 用于指定我们的在哪里查找 import
aidl -I . IHelloService.aidl
编译完成后,项目整体目录如下:
bash
BinderJavaDemo/
└── com
└── yuandaima
├── Android.bp
├── Client.java
├── HelloService.java
├── ICallback.aidl
├── ICallback.java
├── IHelloService.aidl
├── IHelloService.java
└── Server.java
接下来我们修改 Binder 服务端类,主要工作是添加注册回调函数:
java
//HelloService.java
package com.yuandaima;
import android.util.Log;
public class HelloService extends IHelloService.Stub {
private ICallback mCallback;
private static final String TAG = "HelloService";
private int cnt1 = 0;
private int cnt2 = 0;
public void sayhello() throws android.os.RemoteException {
cnt1++;
Log.i(TAG, "sayhello : cnt = "+cnt1);
//调用注册的回调接口
if(mCallback != null) {
mCallback.onMessage("message from server");
}
}
public int sayhello_to(java.lang.String name) throws android.os.RemoteException {
cnt2++;
Log.i(TAG, "sayhello_to "+name+" : cnt = "+cnt2);
return cnt2;
}
//添加注册回调函数
public void registerCallback(int pid, ICallback callback) {
Log.d(TAG, "register callback receive");
mCallback = callback;
}
}
接着修改客户端, 主要定义回调接口以及注册回调接口:
java
//Client.java
package com.yuandaima;
import android.util.Log;
import android.os.ServiceManager;
import android.os.RemoteException;
import android.os.IBinder;
public class Client {
private static final String TAG = "BinderClient";
public static void main(String args[])
{
/* 1. getService */
IBinder binder = ServiceManager.getService("hello");
if (binder == null)
{
Log.i(TAG, "can not get hello service");
return;
}
IHelloService svr = IHelloService.Stub.asInterface(binder);
ICallback callback = new ICallback.Stub() {
@Override
public void onMessage(String message) throws RemoteException {
Log.d(TAG, "onMessage:" + message);
}
};
try {
svr.registerCallback(android.os.Process.myPid(), callback);
} catch (RemoteException e) {
Log.d(TAG, "register callback fail");
e.printStackTrace();
}
try {
svr.sayhello();
Log.i(TAG, "call sayhello");
} catch (Exception e) {
}
try {
int cnt = svr.sayhello_to("hello");
Log.i(TAG, "call sayhello_to " + " : cnt = " + cnt);
} catch (Exception e) {
System.out.println("call sayhello_to , err :"+e);
Log.i(TAG, "call sayhello_to , err : "+e);
}
}
}
最后我们就可以运行我们的程序了:
bash
# 将项目源码放到系统源码下
# 在项目目录下执行
mm
# 将 jar 包 push 到虚拟机上
cd out/target/product/generic_x86_64/system/framework
adb push BinderClient.jar /data/local/tmp
adb push BinderServer.jar /data/local/tmp
# 进入模拟器 shell 环境
adb shell
# 执行 java 程序
export CLASSPATH=/data/local/tmp/BinderClient.jar:/data/local/tmp/BinderServer.jar
# 启动服务端
app_process /data/local/tmp com.yuandaima.Server
# 启动客户端
app_process /data/local/tmp com.yuandaima.Client
查看 log:
bash
logcat | grep BinderClient
可以看出我们的 Client 端已经收到回调消息了,证明我们的回调执行成功了。