Android应用程序互保方案
2016-01-11 23:20
411 查看
在android系统中,到内存不足时系统会主动杀死那些占用内存较多的应用程序,另外像手机管家这种软件也会杀死我们的应用程序。可是由于业务的需求,我们需要应用程序一直在后台运行而不被干掉,因此需要一套可靠的解决方案来实现。
看过网上的不少博客,主要说的都是通过双进程守护,提高service优先级,或者将应用搞成系统级别应用,来实现应用长期在后台运行的效果。这些方案或多或少都有一些缺陷。在此,提出另外一种方案解决这一问题,经过测试,就算被小米管家杀死,也可以立即启动。
**
我们知道,在安卓中是使用binder机制来实现rpc通信的,而不同进程之间service的交互也是依靠binder机制来完成的。
当服务端的binder对象因为种种原因意外死亡时,服务端与客户端之间的连接就会断开,这时候,binder对象会发出一条死亡通知,我们可以监听binder对象的死亡通知,并做一些相应的处理(比如重启应用)
通过调用Binder对象的linkToDeath方法,注册该binder对象的死亡监听;unlinkToDeath方法注销监听。
当binder对象死亡时,会调用DeathRecipient类对象的binderDied函数。
**
创建两个项目app1和app2,在app1和app2中分别声明各自用于与对方发起IPC的interface,
app1和app2中各自构造Service(扩展至android.app.Service)且在Service这个上下文中各自bind到彼此。
籍由Binder机制的便利,app1或app2被杀死,都会通过DeathRecipient接口来告知对方。在这个可被认为实时的通知中,对方便可以辗转通过bind操作来唤醒自己。
特点:不用轮询,且能实时对对方app的消亡做出保活。兼具不拖累性能和反应的及时性
app1
AppService1.java app1的服务
IAppSvc1.aidl 仅仅用来做演示
appService2.java app2的服务
IAppSvc2.aidl 仅仅用来做演示
看过网上的不少博客,主要说的都是通过双进程守护,提高service优先级,或者将应用搞成系统级别应用,来实现应用长期在后台运行的效果。这些方案或多或少都有一些缺陷。在此,提出另外一种方案解决这一问题,经过测试,就算被小米管家杀死,也可以立即启动。
**
原理
**我们知道,在安卓中是使用binder机制来实现rpc通信的,而不同进程之间service的交互也是依靠binder机制来完成的。
当服务端的binder对象因为种种原因意外死亡时,服务端与客户端之间的连接就会断开,这时候,binder对象会发出一条死亡通知,我们可以监听binder对象的死亡通知,并做一些相应的处理(比如重启应用)
通过调用Binder对象的linkToDeath方法,注册该binder对象的死亡监听;unlinkToDeath方法注销监听。
当binder对象死亡时,会调用DeathRecipient类对象的binderDied函数。
**
代码示例
**创建两个项目app1和app2,在app1和app2中分别声明各自用于与对方发起IPC的interface,
app1和app2中各自构造Service(扩展至android.app.Service)且在Service这个上下文中各自bind到彼此。
籍由Binder机制的便利,app1或app2被杀死,都会通过DeathRecipient接口来告知对方。在这个可被认为实时的通知中,对方便可以辗转通过bind操作来唤醒自己。
特点:不用轮询,且能实时对对方app的消亡做出保活。兼具不拖累性能和反应的及时性
app1
AppService1.java app1的服务
[code]public class AppService1 extends Service { protected static final String TAG = "App1"; private final IAppSvc1.Stub mBinder = new IAppSvc1.Stub() { @Override public void getMessage(String message) throws RemoteException { // TODO Auto-generated method stub Log.d(TAG, "getMessage() is invoked!"); } }; IAppSvc2 appSvc2; ServiceConnection svcConn; private ServiceConnection createConnection(boolean forceCreate) { if (!forceCreate && svcConn != null) { return svcConn; } return svcConn = new ServiceConnection() { // Called when the connection with the service is established public void onServiceConnected(ComponentName className, IBinder service) { // Following the example above for an AIDL interface, // this gets an instance of the IRemoteInterface, which we can // use to call on the service appSvc2 = IAppSvc2.Stub.asInterface(service); try { appSvc2.asBinder().linkToDeath(new DeathRecipient() { @Override public void binderDied() { handler.post(new Runnable() { @Override public void run() { Toast.makeText(AppService1.this, "App 2挂了,紧急唤醒中……", Toast.LENGTH_SHORT).show(); } }); handler.postDelayed(new Runnable() { @Override public void run() { //唤醒应用程序app2 wakeupApp2(true); } }, 1000); } }, 0); } catch (RemoteException e) { e.printStackTrace(); } } // Called when the connection with the service disconnects // unexpectedly public void onServiceDisconnected(ComponentName className) { Log.e(TAG, "App1 Service has unexpectedly disconnected"); appSvc2 = null; } }; } private void wakeupApp2(boolean forceCreate) { final Intent intent = new Intent("From App 1"); intent.setComponent(new ComponentName("com.example.app2", "com.example.app2.AppService2")); bindService(intent, createConnection(forceCreate), Context.BIND_AUTO_CREATE); } Handler handler = new Handler(); @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); Log.d(TAG, "onCreate() is invoked!"); Toast.makeText(AppService1.this, "App 1已被唤醒!", Toast.LENGTH_SHORT).show(); wakeupApp2(true); } @Override public void onStart(Intent intent, int startId) { // TODO Auto-generated method stub super.onStart(intent, startId); wakeupApp2(false); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return mBinder; } }
IAppSvc1.aidl 仅仅用来做演示
[code]package com.example.common; interface IAppSvc1 { void getMessage(String msg); }
appService2.java app2的服务
[code]public class AppService2 extends Service { protected static final String TAG = "App2"; private final IAppSvc2.Stub mBinder = new IAppSvc2.Stub() { @Override public void getMessage(String msg) throws RemoteException { // TODO Auto-generated method stub Log.d(TAG, "app 2, getMessage() is invoked!"); } }; IAppSvc1 appSvc1; ServiceConnection svcConn; private ServiceConnection createConnection(boolean forceCreate) { if (!forceCreate && svcConn != null) { return svcConn; } return svcConn = new ServiceConnection() { // Called when the connection with the service is established public void onServiceConnected(ComponentName className, IBinder service) { // Following the example above for an AIDL interface, // this gets an instance of the IRemoteInterface, which we can use to call on the service appSvc1 = IAppSvc1.Stub.asInterface(service); try { appSvc1.asBinder().linkToDeath(new DeathRecipient() { @Override public void binderDied() { // TODO Auto-generated method stub handler.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub Toast.makeText(AppService2.this, "App 1挂了,紧急唤醒中……", Toast.LENGTH_SHORT).show(); } }); handler.postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub wakeupApp1(true); } }, 1000); } }, 0); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // Called when the connection with the service disconnects unexpectedly public void onServiceDisconnected(ComponentName className) { Log.e(TAG, "App1 Service has unexpectedly disconnected"); appSvc1 = null; } }; } Handler handler = new Handler(); @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); Log.d(TAG, "app 2, onCreate() is invoked!"); wakeupApp1(true); Toast.makeText(AppService2.this, "App 2已被唤醒!", Toast.LENGTH_SHORT).show(); } @Override public void onStart(Intent intent, int startId) { // TODO Auto-generated method stub super.onStart(intent, startId); wakeupApp1(false); } private void wakeupApp1(boolean forceCreate) { final Intent intent = new Intent("From App 2"); intent.setComponent(new ComponentName("com.example.app1", "com.example.app1.AppService1")); bindService(intent, createConnection(forceCreate), Context.BIND_AUTO_CREATE); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return mBinder; } }
IAppSvc2.aidl 仅仅用来做演示
[code]package com.example.common; interface IApp2Svc { void getMessage(String msg); }
相关文章推荐
- android studio的assets目录下存放ttf字体格式的问题
- Android Handler详细使用方法实例
- 服务器端启动AVD(Android Virtual Device)
- android 获得各个应用程序缓存大小和清除全部应用缓存
- android 异常捕获
- Android圆角矩形创建工具RoundRect类
- android的ContentProvider
- 下载、编译android4.4.4源码
- [Android]Android自定义View的实现
- Android studio 引入github工程
- android view 滑动
- Android换肤系列 Activity资源拦截与替换
- 安卓绘图的双缓冲机制(看了疯狂Android的双缓冲,自己的一点点感想)
- android开发中显示Installation failed with message INSTALL_FAILED_OLDER_SDK.
- Android 使用Gson解析数组多类型元素
- Android测试点
- android 显示系统初步总结
- Android多媒体-深入音频系列
- Android Dialog
- Android开发中使用MVP模式