Android进程保活攻防

公司在去年年中推出了新的o2o项目,类似于出行软件,需要实时上传经纬度,涉及到了后台Service保活的问题。由于业务场景,保活的问题其实很多开发者都遇到了,网上也有很多人提问,如:怎么让 Android 程序一直后台运行,像 QQ 一样不被杀死?回答者众多,一时间方案纷飞,可是又有几个真能达到希望效果呢?下面结合自身开发经验聊聊各个方案。

一、为什么要保活?

保活的源头是由于我们希望自己服务或者进程能够一直在后台运行,但是总有各种各样的原因导致我们的希望破灭,主要原因有如下几种:1、Android系统回收;2、手机厂商定制管理系统,如电源管理、内存管理等;3、第三方清理软件;4、用户手动结束。

二、保活手段

1、修改Service onStartCommand 方法返回值

当服务被异常终止,是否能重启服务? 一般的做法是修改返回值,返回START_STICKY。
onStartCommand()返回一个整型值,用来描述系统在杀掉服务后是否要继续启动服务,返回值有三种:
START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统将会把它置为started状态,系统不会自动重启该服务,直到startService(Intent intent)方法再次被调用;。
START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
【可行性】除了因为内存不足而被系统回收时少数情况及机型可以重启,其它基本无效。


2、Service onDestory方法重新启动

在onDestory方法发送一个广播,收到广播后,重新启动Service

@Override  
public void onDestroy() {  
stopForeground(true);  
Intent intent = new Intent("com.dwd.service.run.action");  
sendBroadcast(intent);  
super.onDestroy();  
}  

【可行性】在上诉4种原因下Service被干掉,APP进程基本就直接被干掉了,onDestroy方法都不会执行,所以也没法启动服务了。


3、提高Service优先级

Service注册时提高优先级


<service android:name="com.example.helloworld.Service" android:exported="false" >
     <intent-filter android:priority="1000"></intent-filter>
 </service>

【可行性】此方式对Service无效。


4、前台服务

前台服务是被认为是用户已知的正在运行的服务,当系统需要释放内存时不会优先杀掉该进程,前台服务必须有一个 notification 在状态栏中显示。

NotificationCompat.Builder nb = new NotificationCompat.Builder(this);
nb.setOngoing(true);
nb.setContentTitle(getString(R.string.app_name));
nb.setContentText(getString(R.string.app_name));
nb.setSmallIcon(R.drawable.icon);
PendingIntent pendingintent =PendingIntent.getActivity(this, 0,  new Intent(this, AppMain.class), 0);  
nb.setContentIntent(pendingIntent);
startForeground(1423, nb.build());

【可行性】此方法对防止系统回收有一定的效果,可以减少被回收打概率,但是系统在内存极低的情况下,该Service还是会被kill掉,并且不一定会重启。而清理工具或者手动强制结束,进程直接挂掉,并不会重启。


5、进程守护

此方案有两种实现方式,一个是双服务或者两个进程,启动两个服务,相互监听,其中一个挂了,另外一个就会随之把挂了的服务启动起来。另外一种方式是在native层fork一个子进程来与主进程互拉。

【可行性】第一种方式两个进程或者两个服务会同应用进程一起挂掉,所以并不能启动。第二种方式被杀死后确实能唤醒,但是在Android 5.0及以上系统会把fork出来的进程放到一个进程组里, 当程序主进程挂掉后,也会把整个进程组杀掉,因此用fork的方式也无法在Android5.0及以上系统上实现唤醒。


6、监听系统广播

通过监听系统的一些广播,比如:手机开机、解锁屏、网络连接状态变更、应用状态改变等等,然后判断Service是否存活,若否则启动Service。

【可行性】Android系统在3.1版本以后为了加强系统安全性和优化性能对系统广播进行了限制,应用监控手机开机、解锁屏、网络连接状态改变等有规律的系统广播在android3.1以后,首次安装未启动或者用户强制停止后,应用无法监听到。另外最新的Android N取消了网络切换广播,真是心酸啊,一个个都不能用了。


7、应用之间互拉

利用不同的app进程使用广播来进行相互唤醒,比如支付宝、淘宝、天猫、等阿里系的app,如果打开其中任意一个应用,其它阿里系的app也会唤醒了,其实BAT系都差不多。另外现在很多推送sdk也会唤醒app。

【可行性】多个app应用唤醒需要相互之间有关联才能实现,推送sdk应用间唤醒当用户强制停止后无法唤醒。


8、activity一个像素点

在应用退到后台后,另起一个只有 1 像素的页面停留在桌面上,让自己保持前台状态,保护自己不被后台清理工具杀死,此方案是小米曝光腾讯QQ的做法。

【可行性】依然会被杀死。


9、将APK安装到/system/app,变身系统级应用

【可行性】此方法只适合预安装应用,普通应用无法做到变身系统级应用。


10、利用Android系统提供的账号和同步机制实现

在应用中建立一个账户,然后开启自动同步并设置同步间隔时间,利用同步唤醒app。

【可行性】除魅族手机外在大部分手机上此方案可以成功唤醒app,不管是何种方式杀死的。另外小米手机需要关闭神隐模式。


11、白名单

把应用放入手机或者安全软件的白名单中,保证进程不被系统回收,如微信、QQ都在小米的白名单中,所以微信基本不会被系统干掉,但用户可以强制停止。

【可行性】此方案成功率还是不错的,不过用户还是可以手动干掉应用。另外普通的应用如果用户基数不够大,应用开发者去找各大厂商谈,国内android手机厂商多如牛毛,成本太高。但是当应用的装机量及活跃用户达到微信这个规模,也许厂商会主动将你的应用加入白名单呢……


12、伪装播放器

应用启动之后,在后台循环播放一段无声声音,伪装成音乐播放器。

【可行性】此方案成功率很好,在强势如华为的手机上,也能成功保活,但是代价是耗电量非常大,需要谨慎考虑。


点我达应用中综合使用了4、6、7、10及12这五个方案,其中方案12只针对华为机型,能保证90%以上的手机成功保活。Service保活其实是个攻防战,应用为了需求需要实现后台运行,但是系统为了性能安全等因素考虑又不得不干掉偷跑的后台服务。而且保活也是一项持久战,说不定现在可行的方案,某一天又被谷大爷干掉了。学习永无止境,探索永不止步。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值