定制Android系统开发之九——在系统服务中实现回调
2016-01-04 16:28
513 查看
在上一篇博文里,我已经实现了从JNI到Java系统服务的回调。数据已经传回到java里了,那么下面的问题就是如何将数据传回到APP端。这篇博文将解决这个问题。
在前面的博文里,我曾说过,Android中的系统服务是客户端/服务器模式,所以,在下文中,客户端统一指SystemManager,服务端统一指SystemManagerService。
然后在SystemManager中定义注册回调的函数:
这样的实现方式,只需要用传入SystemManager的SystemManagerListener构造一个SystemManagerListenerTransfer,用这个Transfer传入SystemManagerService即可。当在Service中调用Transfer的onProgress的时候,实际上调用的就是Listener的onProgress。
到这里,在服务端中实现registerListener函数就很简单了,这里直接贴代码:
在前面的博文里,我曾说过,Android中的系统服务是客户端/服务器模式,所以,在下文中,客户端统一指SystemManager,服务端统一指SystemManagerService。
在客户端中定义注册回调的函数
第一步,当然是定义一个Listener接口。在framework/base/core/java/android/os/下定义SystemManagerListener接口如下:package android.os; public interface SystemManagerListener { /** * @param process */ void onProgress(int process); }
然后在SystemManager中定义注册回调的函数:
/** * 注册回调。 * * @param listener * @return 成功返回0,失败请参考错误码ErrorCode */ public int registerListener(SystemManagerListener listener) {}
在服务端中实现注册回调的函数
我们知道,在系统服务的模型中,客户端的工作只有一个,就是调用服务端的对应的函数,所以在registerListener中,将调用SystemManagerService中的registerListener函数。那么,问题来了,SystemManagerService中的registerListener是在ISystemManager.aidl中实现的,但是aidl的参数不能直接传递普通的接口,只能传递由aidl定义的接口。而我们的SystemManagerListener需要暴露给APP端,只能是个普通的接口,不能用aidl来定义。这个矛盾怎么解决呢?我在LocationManager中找到了解决方案(所有的问题都可以在Android源码中找到参考!!!),那就是定义一个SystemManagerListenerTransfer类实现ISystemManagerListener.aidl定义的接口。代码如下:// 定义ISystemManagerListener interface ISystemManagerListener{ /** * @param process */ void onProgress(int process); } // ======================================================= // 在ISystemManager中定义registerListener函数 import android.os.iflytek.ISystemManagerListener; /** * 注册回调。 * * @param listener * @return 成功返回0,失败请参考错误码ErrorCode */ int registerListener(ISystemManagerListener listener); // ======================================================= // 实现SystemManagerListenerTransfer public class SystemManagerListenerTransfer extends ISystemManagerListener.Stub{ private static final String TAG = "TimothySystemManagerListenerTransfer"; private SystemManagerListener mListener; public SystemManagerListenerTransfer(SystemManagerListener listener){ this.mListener = listener; } @Override public void onProgress(int process) throws RemoteException { Log.d(TAG, "onProgress() is called, process = " + process); mListener.onProgress(process); } }
这样的实现方式,只需要用传入SystemManager的SystemManagerListener构造一个SystemManagerListenerTransfer,用这个Transfer传入SystemManagerService即可。当在Service中调用Transfer的onProgress的时候,实际上调用的就是Listener的onProgress。
到这里,在服务端中实现registerListener函数就很简单了,这里直接贴代码:
public int registerListener(ISystemManagerListener listener) throws RemoteException { Log.d(TAG, "registerListener() is called"); this.mSystemManagerListener = listener; }
在客户端中实现注册回调的函数
回过头来,实现SystemManager中registerListener如下:try { SystemManagerListenerTransfer transfer = new SystemManagerListenerTransfer(listener); return mService.registerListener(transfer); } catch (RemoteException e) { e.printStackTrace(); return SystemManagerCons.ErrorCode.ERROR_REMOTE_EXCEPTION; }
实现注销Listener函数
注销Listener的实现过程和注册类似,只需在SystemManagerService的unregisterListener中将mSystemManagerListener置空即可。回调函数的调用
调用这个回调函数就很简单了,在JNI的java函数里面,使用下面的一行代码即可:mSystemManagerListener.onProgress(xxx);
写在最后
有一点要注意:所有的aidl都要在Android.mk中声明,不然编译一定会出错哦!!!相关文章推荐
- Android编程开发之TextView单击链接弹出Activity的方法
- Android QQ音乐/酷狗音乐锁屏控制实现原理,酷狗锁屏
- Android fragment 重叠问题——通过hide,show方式导致的解决方法
- Android 读取SD卡指定后缀的所有文件
- android用户界面之Gallery3D学习资料汇总
- Android 关闭软键盘
- Android SDK Manager国内更新代理
- Android Studio如何发布APK
- Android练兵--Material加载进度条
- [Android实例] 带clean按钮的输入框
- Activity的启动模式(android:launchMode)
- ndk-stack的使用
- 关于android设计理念
- Gradle android自动填写SVN号,并发布(拷贝)到指定目录
- Android开发秘籍学习笔记(十二)
- Android:样式和主题
- adb push 失败提示 ‘Read-only file system’
- [Android实例] 侧边字母滑动检索控件
- Android:屏幕适配
- android系统调用百度DistanceUtil.getDistance()死机