Android 跨进程传递点击事件
1 在与远程(即另一进程)的service进行通信的时候,需要在远程建立一个aidl接口文件。接口文件定义在src目录下的自建的包内,如
其中ICalcAIDL文件为主接口文件,其内容为
①之前有个错误是在interface前面加上了public,编译器报错
编辑好之后默认会在gen文件夹下面生成对应的.java文件,即ICalcAIDL.java
服务端service用到的就是这个接口的内部类ICalcAIDL.Stub,它是一个Binder对象,从源码中可以看到
public static abstract class Stub extends android.os.Binder implements com.txt.aidl.ICalcAIDL
另外有两个我们定义的方法需要实现
public int add(int x, int y) throws android.os.RemoteException;
public int max(int x, int y) throws android.os.RemoteException;
service中onBind方法返回的Binder对象定义如下:
2 客户端activity工程中,需要把服务端gen文件夹下面生成的接口类,即全部导入com.txt.aidl包内文件,目前只有ICalcAIDL.java这个文件
然后activity中定义ServiceConnection对象,从而获得ICalcAIDL对象
拿到mClacAIDL对象后,就和服务端service关联上了,操作该对象的add()和max()方法就能主动通知service做具体的事情了。
activity主动通知service做事情的大致流程就是这样建立起来的了。
3 那么远程service如何主动通知本地activity做什么事情呢,显然我们需要使用回调接口。(同一进程中的activity和service双向通信也是需要在activity中注册一个service提供的回调接口来实现的)。
这里由于是跨进程,这里的回调接口也必须是定义成aidl文件形式②,我的第二个错误就是犯在这里的。
我在ICalcAIDL接口中定义一个注册回调的方法
void register(IListener ilistener);
刚开始我把IListener 这个接口直接定义成java文件,结果在ICalcAIDL接口编译器就报错了,说找不到这个IListener 接口的定义。
后来我把IListener 这个接口也定义成aidl文件,结果就正确了。
所以我得出一个结论,在某个aidl文件中使用到的其他类的对象,必须也是由aidl文件定义的。
于是,我在服务端的工程中的com.txt.aidl包中又定义了这个回调接口IListener.aidl
并在ICalcAIDL中增加了注册函数
这样我的service中的binder对象就增加了一个注册方法
当我需要通知activity做事情的时候,只要调用这个接口的方法就行了。
这样服务端的工程文件就变成这样了
4 客户端activity工程中同样需要把IListener.java文件加入到com.txt.aidl包中
客户端activity在serviceConnection对象中注册一个IListener回调接口
在这里,我犯了第3个错误,
③在register方法里面我传入了一个IListener对象,而不是IListener.Stub对象,这就直接导致,服务端调用回调接口的change()并不能触发客户端的change()方法。
显然,这里必须使用Stub这个子类来实例化Ilistener对象。
ps:有时候总是止于一知半解,这是第三次学习跨进程通信了,感觉又进步了一点点。
<< 上一篇
下一篇 >>