很久没用跨进程通信了,然后等自己又要用的时候,网上一搜,千遍一律,还很渣,吐血~
工程有两份`MessengerService`&`MessengerActivity`,前个提供服务,后个访问服务。
跨进程通信
就多个apk互相通信,当然广播也是不错的。不过这里用的是Messenger和AIDL,并且都弄成双向的了。
Messenger
信使,底层说是也用的AIDL。用起来挺方便的。
MessengerService
1)AndroidManifest.xml声明权限
- <permission
- android:name="org.join.permission.SERVICE"
- android:protectionLevel="normal" >
- </permission>
-
- <uses-permission android:name="org.join.permission.SERVICE" />
为什么弄个带权限的呢?因为讨厌任何警告==。
2)注册MessengerService
- <service
- android:name="org.join.messenger.MessengerService"
- android:exported="true"
- android:permission="org.join.permission.SERVICE"
- android:process=":remote" >
- <intent-filter>
- <action android:name="org.join.service.MESSENGER" />
- </intent-filter>
- </service>
这里把权限加上了,不然最新ADT是会有个警告的。就一嘀咕的老头,讨人厌。
3)MessengerService核心代码
- public class MessengerService extends Service implements MessageCode {
-
- static final String TAG = "MessengerService";
-
- public static final String ACTION = "org.join.service.MESSENGER";
-
-
- final Messenger mMessenger = new Messenger(new Handler() {
-
-
- @Override
- public void dispatchMessage(Message msg) {
- switch (msg.what) {
- case CLNT_REQ_HELLO:
- toast("Hello!");
- Bundle data = new Bundle();
- data.putString("msg", "Who am I?");
-
- respClnt(msg.replyTo, SERV_RES_HAHA, data);
- break;
- case CLNT_REQ_SURPRISE:
- String s = msg.getData().getString("msg");
- toast("Surprise! " + s);
- break;
- }
- }
-
-
- private void respClnt(Messenger clnt, int msgCode, Bundle data) {
- if (clnt == null) {
- return;
- }
- try {
- Message msg = Message.obtain(null, msgCode);
- msg.replyTo = mMessenger;
- if (data != null) {
- msg.setData(data);
- }
- clnt.send(msg);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
- });
-
- @Override
- public IBinder onBind(Intent intent) {
- Log.e(TAG, "onBind");
- return mMessenger.getBinder();
- }
-
-
-
- }
MessengerActivity
1)AndroidManifest.xml声明权限
- <uses-permission android:name="org.join.permission.SERVICE" />
2)MessengerActivity核心代码
1. 创建Messenger
-
- private Messenger mService;
-
-
- final Messenger mMessenger = new Messenger(new Handler() {
-
-
- @Override
- public void dispatchMessage(Message msg) {
- switch (msg.what) {
- case SERV_RES_HAHA:
- String s = msg.getData().getString("msg");
- toast("HAHA! " + s);
- Bundle data = new Bundle();
- data.putString("msg", "I am you.");
- sendMsg(CLNT_REQ_SURPRISE, data);
- break;
- }
- }
- });
-
-
- private void sendMsg(int msgCode, Bundle data) {
- if (mService == null) {
- toast("Service is disconnected!");
- return;
- }
- try {
- Message msg = Message.obtain(null, msgCode);
- msg.replyTo = mMessenger;
- if (data != null) {
- msg.setData(data);
- }
- mService.send(msg);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
2. 绑定Service
-
- private ServiceConnection servConnection = new ServiceConnection() {
-
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- mService = new Messenger(service);
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- mService = null;
- }
- };
-
-
- protected void doBindService() {
- bindService(new Intent("org.join.service.MESSENGER"), servConnection, BIND_AUTO_CREATE);
- isBound = true;
- }
-
-
- protected void doUnbindService() {
- if (isBound) {
- unbindService(servConnection);
- isBound = false;
- }
- }
好了,客户端要发送消息,调用sendMsg()就可以了。
AIDL
也挺简单的,恩,继续...
RemoteService
1)AndroidManifest.xml声明权限,就之前的,ok了。
2)注册RemoteService
- <service
- android:name="org.join.aidl.RemoteService"
- android:exported="true"
- android:permission="org.join.permission.SERVICE"
- android:process=":remote" >
- <intent-filter>
- <action android:name="org.join.service.AIDL" />
- </intent-filter>
- </service>
3)搞个parcelable对象
不能就用基本类型是不,所以要搞个对象^^。
恩,Event.java就是了。然后要为它写个aidl。
Event.aidl
- package org.join.aidl;
-
- parcelable Event;
简单吧。
4)然后弄个Callback
不能就单向通信是不,所以要用来回调客户端。
IRemoteCallback.aidl
- package org.join.aidl;
-
- import org.join.aidl.Event;
-
- /**
- * @brief 远程回调
- * @author join
- */
- interface IRemoteCallback {
-
- void onEvent(in Event event);
-
- }
4)服务的AIDL了
IRemoteService.aidl
- package org.join.aidl;
-
- import org.join.aidl.IRemoteCallback;
- import org.join.aidl.Event;
-
- /**
- * @brief 远程服务
- * @author join
- */
- interface IRemoteService {
-
- void registerCallback(in IRemoteCallback cb);
-
- void unregisterCallback(in IRemoteCallback cb);
-
- Event requestEvent();
-
- }
5)哦,总算到RemoteService了
RemoteService.java,恩,直接参考了ApiDemo,捂脸~
- public class RemoteService extends Service {
-
- static final String TAG = "RemoteService";
-
- public static final String ACTION = "org.join.service.AIDL";
-
- final RemoteCallbackList<IRemoteCallback> mCallbacks = new RemoteCallbackList<IRemoteCallback>();
-
- private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
-
- @Override
- public void registerCallback(IRemoteCallback cb) throws RemoteException {
- if (cb != null)
- mCallbacks.register(cb);
- }
-
- @Override
- public void unregisterCallback(IRemoteCallback cb) throws RemoteException {
- if (cb != null)
- mCallbacks.unregister(cb);
- }
-
- @Override
- public Event requestEvent() throws RemoteException {
- Event event = new Event();
- event.setId(Integer.MAX_VALUE);
- event.setName("Are you?");
- return event;
- }
- };
-
- private static final int REPORT_EVENT = 1;
-
- private final Handler mHandler = new Handler() {
-
- private Event event = new Event();
- private int count = 0;
-
- @Override
- public void dispatchMessage(Message msg) {
- switch (msg.what) {
- case REPORT_EVENT: {
- event.setId(count);
- event.setName("name" + count);
- count++;
-
-
- final int N = mCallbacks.beginBroadcast();
- for (int i = 0; i < N; i++) {
- try {
- mCallbacks.getBroadcastItem(i).onEvent(event);
- } catch (RemoteException e) {
-
- }
- }
- mCallbacks.finishBroadcast();
-
-
- sendMessageDelayed(obtainMessage(REPORT_EVENT), 1 * 1000);
- }
- break;
- default:
- super.handleMessage(msg);
- }
- }
- };
-
- @Override
- public IBinder onBind(Intent intent) {
- Log.e(TAG, "onBind");
- return mBinder;
- }
-
- @Override
- public void onCreate() {
- Log.e(TAG, "onCreate");
- super.onCreate();
- mHandler.sendEmptyMessage(REPORT_EVENT);
- }
-
- @Override
- public void onDestroy() {
- Log.e(TAG, "onDestroy");
- super.onDestroy();
- mHandler.removeMessages(REPORT_EVENT);
- }
-
-
-
- }
只要这个服务开启,每1秒回调下onEvent()。
至于RemoteCallbackList,是方便我们管理的,不然在RemoteException时,我们要亲自remote才行。
MessengerActivity
1)AndroidManifest.xml声明权限,也是之前的,ok了。
2)然后,之前辛苦工作的奖励时间^^
把Event.java、Event.aidl、IRemoteCallback.aidl、IRemoteService.aidl拷贝过来,开心吧。
3)还是MessengerActivity内绑定
1. 回调和请求
-
- private IRemoteService mRemoteService = null;
-
-
- private IRemoteCallback mCallback = new IRemoteCallback.Stub() {
- @Override
- public void onEvent(Event event) throws RemoteException {
- mHandler.sendMessage(mHandler.obtainMessage(BUMP_EVENT, event));
- }
- };
-
- private static final int BUMP_EVENT = 1;
-
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case BUMP_EVENT:
- Event event = (Event) msg.obj;
- tvEvent.setText(event.toString());
- break;
- default:
- super.handleMessage(msg);
- }
- }
-
- };
-
-
- public void reqEvent(View v) {
- Event event = null;
- try {
- if (mRemoteService != null) {
- event = mRemoteService.requestEvent();
- }
- } catch (RemoteException e) {
- } finally {
- toast(event == null ? "Remote service is disconnected!" : event.toString());
- }
- }
2. 绑定Service
-
- private ServiceConnection servRemoteConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- mRemoteService = IRemoteService.Stub.asInterface(service);
- tvEvent.setText("Attached.");
- try {
- mRemoteService.registerCallback(mCallback);
- } catch (RemoteException e) {
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- mRemoteService = null;
- btnServAidl.setChecked(false);
- tvEvent.setText("Disconnected.");
- }
- };
-
- protected void doBindRemoteService() {
- bindService(new Intent("org.join.service.AIDL"), servRemoteConnection, BIND_AUTO_CREATE);
- isRemoteBound = true;
- tvEvent.setText("Binding.");
- }
-
- protected void doUnbindRemoteService() {
- if (isRemoteBound) {
- unbindService(servRemoteConnection);
- isRemoteBound = false;
- }
- }
哦也,all done。
礼物
附赠两个小工程
`AndroidFragment`
- Fragment组件的例子。
- 主要注释,一些方法说明&注意点。
`AndroidJUnit`
- Run as -> Android JUnit test。
- 主要代码,src/test目录下。