用任何一款具备任务管理器功能的应用,尝试去关闭360安全卫士时,会发现360进程是无法被关闭的。
首先,明确一个前提——360没有roo权限的。那它是如何做到的呢?
先说一下Android上的进程的优先级。在Android上,系统为了管理内存释放有限的空间,会根据优先级杀掉一些进程,进程优先级越低的优先被清除。
从高到低依次是:
foreground process
visible process
service process
background process
empty process。
Service它还是在主线程跑,要做耗时的工作还得在Service里面另起一个线程,倒不如直接就这样做而不用 Service? 原来用了Service来处理是为了保证这个工作有较高的优先级,从上面可看到它排在第3,如果不通过Service直接启动线程则当 Activity退出或暂停的时候,该线程很容易被杀掉,用Service可以有效地保护起来。
这就解释一个现象:在Activity里起一个Thread,并处于wait状态时,会很容易被kill掉的原因。
再到说题目,为什么360的进程无法被删除? 实验证明,只要进程被修改foreground级别,就不会被任务管理器关闭,但在使用之前,有一点小窍门。
在1.5固件之前,Service提供了一个setForeground(boolean enable),可以把当前进程的优化级提升到foreground的级别。1.5固件之后,google把setForeground(boolean enable)废弃了,改为startForeground(int id, Notification
notification),意味着需要开发者强制弹提示以告之用户。 因此,如果要同时兼容两个版本,就需要用反射机制来实现的,这不再详说。 这里会产生一个矛盾:如果需要一个foreground的进程,但又不希望出现notification提示,怎么办? 这个矛盾在1.5之前是不存在的,1.5之后就需要用点“怪招”了。
经验证,一个notification的icon,只要不设置任何值(其它值可以任意设置),那通过NotificationManager.notify是不会显示出来的。这样的话,通过如下方式启动Service,就可以得到foreground而不需求显示notification了,代码如下:
public final class MyService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
startForeground();
}
private void startForeground(){
Notification notification = new Notification();
notification.tickerText = "哈哈";
notification.setLatestEventInfo(this, "HI", "HI", PendingIntent.getActivity(this, 0, new Intent(), 0));
startForeground(665248, notification);
}
}