保持应用后台,熄屏状态下继续运行
来源:互联网 发布:淘宝统一改运费模板 编辑:程序博客网 时间:2024/04/29 04:42
如何让你的App永远在后台存活:对Android进程守护、闹钟后台被杀死的研究。
最近公司要求要做一个提醒功能,一说到提醒,那肯定就和闹钟差不多的意思,那么肯定就要用到AlarmManager。
但是,我们知道,android系统很坑爹,不同的厂商对rom的定制,导致对进程的管理都不太相同,但是如何做到在各个手机上都能一直保持后台执行呢?。
为了解决这个问题,特地去研究了各种保持进程不被杀死的方法。
下面对几种常见的用法进行了分析,并且给出了我自己发现的一个保持进程运行的方法。
方法1:在原生的Android系统上使用AlarmManager
方法2:通过AIDL实现双进程守护机制
方法3:MarsDaemon第三方库,实现进程常驻
方法4:通过AppWiget,android桌面小组件保持进程的运行
下面是具体分析
方法1:在原生的Android系统上使用AlarmManager
“原生”这个词就对这个方法的限定很大了。我尝试了很多次,在原生的操作系统中,不需要特殊的去调用service处理。直接在某个Activity中通过AlarmManager的set和setRepeating方法设置定时后,就去杀了进程,测试结果显示,闹钟还是可以继续响的。但是这种不去特殊处理的,在第三方的rom基本都是不行的,相信大家每人敢用,因此知道就可以了
方法2:通过AIDL实现双进程守护机制
网上有很多关于AIDL实现双进程守护机制的文章,内容都是差不多,关于这种方法,都是通过在MainFest文件中指定某个Service android:process=":remote",这样就可以使这个service单开一个进程来运行。在主进程中有一个MainService,一旦RemoteService所在进程被杀死,MainService就会立刻去重新启动它,同样的,当MainService被杀死了,RemoteService就会去启动MainService,两个进程的两个Service互相监控来实现进程不销毁。
大致方法为:
1、创建一个IMyAIDLInterface.aidl文件
[java]
//IMyAidlInterface.aidl
packagecom.xiaoqi.alarmmanagerdemo;
interfaceIMyAidlInterface{
StringgetServiceName();
}
2、创建一个LocalService:
[java]
publicclassLocalServiceextendsService{
MyBinderbinder;
MyConnconn;
@Nullable
@Override
publicIBinderonBind(Intentintent){
returnbinder;
}
@Override
publicvoidonCreate(){
super.onCreate();
binder=newMyBinder();
conn=newMyConn();
}
classMyBinderextendsIMyAidlInterface.Stub{
@Override
publicStringgetServiceName()throwsRemoteException{
returnLocalService.class.getSimpleName();
}
}
@Override
publicintonStartCommand(Intentintent,intflags,intstartId){
Toast.makeText(LocalService.this,"本地服务活了",Toast.LENGTH_SHORT).show();
this.bindService(newIntent(LocalService.this,RomoteService.class),conn,Context.BIND_IMPORTANT);
returnSTART_STICKY;
}
classMyConnimplementsServiceConnection{
@Override
publicvoidonServiceConnected(ComponentNamename,IBinderservice){
Log.i("yangqing","绑定上了远程服务");
}
@Override
publicvoidonServiceDisconnected(ComponentNamename){
Log.i("yangqing","远程服务被干掉了");
Toast.makeText(LocalService.this,"远程服务挂了",Toast.LENGTH_SHORT).show();
//开启远程服务
LocalService.this.startService(newIntent(LocalService.this,RomoteService.class));
//绑定远程服务
LocalService.this.bindService(newIntent(LocalService.this,RomoteService.class),conn,Context.BIND_IMPORTANT);
}
}
@Override
publicvoidonDestroy(){
super.onDestroy();
//开启远程服务
LocalService.this.startService(newIntent(LocalService.this,RomoteService.class));
//绑定远程服务
LocalService.this.bindService(newIntent(LocalService.this,RomoteService.class),conn,Context.BIND_IMPORTANT);
}
}
3、创建一个RemoteService:
[java]
publicclassRomoteServiceextendsService{
MyConnconn;
MyBinderbinder;
@Nullable
@Override
publicIBinderonBind(Intentintent){
returnbinder;
}
@Override
publicvoidonCreate(){
super.onCreate();
conn=newMyConn();
binder=newMyBinder();
}
@Override
publicintonStartCommand(Intentintent,intflags,intstartId){
Toast.makeText(this,"远程服务活了",Toast.LENGTH_SHORT).show();
this.bindService(newIntent(this,LocalService.class),conn,Context.BIND_IMPORTANT);
returnSTART_STICKY;
}
classMyBinderextendsIMyAidlInterface.Stub{
@Override
publicStringgetServiceName()throwsRemoteException{
returnRomoteService.class.getSimpleName();
}
}
classMyConnimplementsServiceConnection{
@Override
publicvoidonServiceConnected(ComponentNamename,IBinderservice){
Log.i("yangqing","绑定本地服务成功");
//Toast.makeText(RomoteService.this,"绑定本地服务成功",Toast.LENGTH_SHORT).show();
}
@Override
publicvoidonServiceDisconnected(ComponentNamename){
Log.i("yangqing","本地服务被干掉了");
Toast.makeText(RomoteService.this,"本地服务挂了",Toast.LENGTH_SHORT).show();
//开启本地服务
RomoteService.this.startService(newIntent(RomoteService.this,LocalService.class));
//绑定本地服务
RomoteService.this.bindService(newIntent(RomoteService.this,LocalService.class),conn,Context.BIND_IMPORTANT);
}
}
@Override
publicvoidonDestroy(){
super.onDestroy();
//开启本地服务
RomoteService.this.startService(newIntent(RomoteService.this,LocalService.class));
//绑定本地服务
RomoteService.this.bindService(newIntent(RomoteService.this,LocalService.class),conn,Context.BIND_IMPORTANT);
}
}
4、在AndroidMainfest文件中注册:
[html]
使用方法:
[java]
Intentservice=newIntent(this,LocalService.class);
startService(service);
IntentremoteService=newIntent(this,RomoteService.class);
startService(remoteService);
这样就可以了,但是经过测试发现,我们在应用管理中,会发现确实有两个进程,我们单独的去关闭一个,另一个马上就会把它开启,但是如果我们之间去杀进程,发现只有在vivo手机中,确实可以保持不被杀死,但是在其他手机中,整个后台进程还是被杀死了。说明这个方法也不是很可靠的。
方法3:MarsDaemon第三方库,实现进程常驻
地址:https://github.com/Marswin/MarsDaemon
守护进程也有第三方库,相信很多人都没想到吧
这个库的使用也非常简单,底层通过jni来实现了进程守护,这边就不给出使用方法了,直接在github上看就行了。
但是我实际使用发现,在华为机器上依然不能进程保持运行,只要一清理,后台的闹钟就没有效果了。但是在某些机型上还是可以用的,可靠性比通过AIDL的双进程守护效果好,可是依然不能保证运行。
方法4:通过AppWiget,android桌面小组件保持进程的运行
尝试了网上的很多方法,都是进程一清理,所以程序都被停止了,尤其在华为手机上,360都没法保持一直运行,因此我觉得这个想让后台服务永久运行的想法越来越不可靠。
我在应用商店上下载了一个排行第一的闹钟软件,但是经过多次测试,结果都是一样,想要后台进行,基本是不可能。QQ是通过一个像素点,一直显示在最前,这种黑科技来保持进程一直在,于是我想到了,如果我们添加一个桌面组件来,这样这个组件也是App的一部分, 但它却一直运行在那,这样是否就可以让进程杀死了,程序还是能运行呢?
于是我测试了一下,写了一个很简单AppWidget组件,在AppWifgetProvider中,写了一个简单的闹钟程序,并且让AppWidget中的TextView的数字一直自增1。写完之后我测了一下,发现这个方法是可行的。即使是在华为手机上,我把进程清理了,闹钟还是会响,AppWidget上的数字也一直在更新。
关于AppWidget的写法网上也很多,这边就不具体给出了。在测试这个方法的时候,我发现刚刚下载的闹钟软件也有桌面小组件,我添加了之后,再进行闹钟测试,居然发现,在进程杀死后,闹钟居然可以继续执行,即使是锁屏状态,很明显,这个软件使用的方法和我想到的是一样的。
通过AppWidget来保持进程中代码的执行,这个应该还其他博客中还没有被提到,这个方法相比其他的方法而言,已经是非常可靠的了。但是这个局限也挺大,就是必须通过一个AppWidget来实现。
关于进程守护已经分析完了,如果有什么更好的方法,欢迎大家分析。
- 保持应用后台,熄屏状态下继续运行
- Android锁屏状态下保持后台唤醒WakeLock机制
- 继续保持良好状态
- 如何使应用保持后台运行
- HttpClient保持登录cookie状态,继续操作
- iOS 保持程序后台运行
- ios-multitasking-应用转入后台时,如何继续后台运行任务
- ios-multitasking-应用转入后台时,如何继续后台运行任务
- 使程序在Linux下后台运行 (关掉终端继续让程序运行的方法)
- 使程序在Linux下后台运行 (关掉终端继续让程序运行的方法)
- 使程序在Linux下后台运行 (关掉终端继续让程序运行的方法)
- 使程序在Linux下后台运行 (关掉终端继续让程序运行的方法)
- 使程序在Linux下后台运行 (关掉终端继续让程序运行的方法)
- 使程序在Linux下后台运行 (关掉终端继续让程序运行的方法)
- 使程序在Linux下后台运行 (关掉终端继续让程序运行的方法)
- 应用程序通过WakeLock保持后台唤醒状态
- Android应用程序 --- WakeLock 保持后台唤醒状态
- Android应用程序 --- WakeLock 保持后台唤醒状态
- ArcGIS设置地图服务的底图
- java 多态摘录
- 在Windows下为PHP5.6安装redis扩展和memcached扩展
- 升级安装php7要考虑的几个方面
- BlockingDeque&BlockingQueue区别
- 保持应用后台,熄屏状态下继续运行
- jd学习笔记
- LeetCode题解 #3 Longest Substring Without Repeating Characters
- 弘智教育-效果图-0-需要注意的点
- PathVariable annotation was empty on param 0.
- 关于VS2013 mfc使用Edit control控件显示输出内容问题
- Oracle SQL Developer : SQL格式化
- c++ unodered_set
- 关于document.onkeydown用法(按下回车提交)