保持应用后台,熄屏状态下继续运行

来源:互联网 发布:淘宝统一改运费模板 编辑:程序博客网 时间: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来实现。

关于进程守护已经分析完了,如果有什么更好的方法,欢迎大家分析。

阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 洗手盆缝隙漏水怎么办 洗手盆裂缝漏水怎么办 洗手盆堵了怎么办 征信账号注册怎么办 注册不了征信号怎么办 阿里巴巴一键铺货到淘宝发货怎么办 淘宝购物的问题怎么办 买家评价被删除怎么办 淘宝订单虚假交易怎么办 被判定虚假物流怎么办 淘宝有虚假交易怎么办 微信辅助不了怎么办 微信验证失败怎么办 淘宝占空间太大怎么办 淘宝占用空间大怎么办 ipad空间不够用怎么办 ipadmini密码忘了怎么办 旧ipad特别卡怎么办 苹果ipad反应慢怎么办 手机垃圾多了怎么办 ipad2内存过低怎么办 苹果平板ipad内存不足怎么办 手机dns配置错误怎么办 蓝牙已停止运行怎么办 ipad看电视闪退怎么办 ipad为什么看电视会闪退怎么办 微淘直播延迟怎么办 手机淘宝进群领金币怎么办 做淘客冲销量停止淘客后怎么办 微信中零钱提现怎么办 淘宝买家不签收怎么办 小龙虾没人下单怎么办 淘宝直播不浮现怎么办 淘宝直播看不了怎么办 理财客户说没钱怎么办 投资不给钱了怎么办 工作中遇到挫折怎么办 手机qq出现异常怎么办 农行卡出现异常怎么办 淘宝长期不发货怎么办 快递一直不发货怎么办