本篇文章介绍如何在Framework添加一个系统服务,来完成同Client的跨进程通信。
(1)Server端
在服务端添加如下代码:
(A)服务回调的AIDL
//frameworks/base/core/java/com/callback/
// ICallbackTestCallback.aidl
package com.callback;
interface ICallbackTestCallback {
/**
* 服务端调用客户端的回调
**/
void onReceived(String msg);
}
(B)服务接口的AIDL
//frameworks/base/core/java/com/callback/
// ICallBackTestInterface.aidl
package com.callback;
import com.callback.ICallbackTestCallback;
interface ICallBackTestInterface {
// 向服务端注册客户端回调
void register(ICallbackTestCallback callback);
// 向服务端注销客户端回调
void unregister(ICallbackTestCallback callback);
// 向服务端发送消息
void callServer(String msg);
}
(C)服务端Service的实现
//frameworks/base/services/core/java/com/android/server/CallBackTestService.java
package com.android.server;
import android.util.Slog;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.Binder;
import android.os.IBinder;
import com.callback.ICallbackTestCallback;
import com.callback.ICallBackTestInterface;
public class CallBackTestService extends ICallBackTestInterface.Stub {
private final String TAG = "testcallback";
private final RemoteCallbackList<ICallbackTestCallback> mRemoteClients = new RemoteCallbackList<>();
public CallBackTestService(){
}
public void register(ICallbackTestCallback callback) throws RemoteException {
Slog.d(TAG,"register callback from pid=" + Binder.getCallingPid());
mRemoteClients.register(callback);
}
public void unregister(ICallbackTestCallback callback) throws RemoteException {
Slog.d(TAG,"unregister callback from pid=" + Binder.getCallingPid());
mRemoteClients.unregister(callback);
}
public void callServer(String msg) throws RemoteException {
Slog.d(TAG,"received pid=" + Binder.getCallingPid()+" message: " + msg);
}
private void noteClients(String msg){
int cb = mRemoteClients.beginBroadcast();
for(int i=0;i<cb;i++){
try {
//通知注册的客户端
mRemoteClients.getBroadcastItem(i).onReceived(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
mRemoteClients.finishBroadcast();
}
}
(D)服务端Manager的实现
//frameworks/base/core/java/com/callback/CallBackTestManager.java
package com.callback;
import android.util.Slog;
import android.content.Context;
import android.os.RemoteException;
import com.callback.ICallbackTestCallback;
import com.callback.ICallBackTestInterface;
public class CallBackTestManager {
public static final String SERVICE_NAME = "callbacktest";
private final ICallBackTestInterface mService;
public CallBackTestManager(Context context, ICallBackTestInterface service){
mService = service;
}
public void register(ICallbackTestCallback callback) {
try{
mService.register(callback);
} catch (RemoteException e){
throw e.rethrowFromSystemServer();
}
}
public void unregister(ICallbackTestCallback callback) {
try{
mService.unregister(callback);
} catch (RemoteException e){
throw e.rethrowFromSystemServer();
}
}
public void callserver(String msg) {
try{
mService.callServer(msg);
} catch (RemoteException e){
throw e.rethrowFromSystemServer();
}
}
}
(2)Client端(应用)
.
├── aidl
│ └── com
│ └── callback
│ ├── ICallbackTestCallback.aidl
│ └── ICallBackTestInterface.aidl
├── AndroidManifest.xml
├── java
│ └── com
│ └── callback
│ ├── CallBackTestManager.java
│ └── demo
│ └── MainActivity.java
其中,ICallbackTestCallback.aidl、ICallBackTestInterface.aidl、CallBackTestManager.java三个文件都是从我们添加到源码里面拷贝出来的,因为Android Studio的sdk里面并没有这些实现,把这些文件放到工程的目录里面,让编译可以通过。
package com.callback.demo;
import com.callback.ICallbackTestCallback;
import com.callback.CallBackTestManager;
import com.testcallback.demo.R;
public class MainActivity extends AppCompatActivity {
private final String TAG = "testcallback";
CallBackTestManager mCallbackSerice = null;
private boolean bound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
if(bound){
registerCallback();
}
}
@Override
protected void onPause() {
super.onPause();
if(bound){
unregisterCallback();
}
}
public void bindService() {
if(mCallbackSerice == null){
mCallbackSerice = (CallBackTestManager)getSystemService(CallBackTestManager.SERVICE_NAME);
bound = true;
}
}
private ICallbackTestCallback mCallback = new ICallbackTestCallback.Stub(){
@Override
public void onReceived(String msg) throws RemoteException {
Log.d(TAG,"received msg: " + msg + " . from server pid=" + Binder.getCallingPid());
}
};
public void registerCallback() {
if(mCallbackSerice!=null){
mCallbackSerice.register(mCallback);
}
}
public void unregisterCallback() {
if(mCallbackSerice!=null){
mCallbackSerice.unregister(mCallback);
}
}
public void notifyService(View view) {
if(mCallbackSerice!=null){
mCallbackSerice.callserver("hello, I'm client");
}
}
}