需求是做一个自家Android设备上的应用市场,开机自启动,每分钟向后台请求是否有应用要更新。
原生的系统开机自启动很容易(很多定制的系统会限制自启动)。利用开机广播启动service A,service A里启动监听ACTION_TIME_TICK的广播,每分钟请求数据一次。这个时候应用的进程里只有一个后台服务,长按home键是不会出现该应用的,也就是说通过长按home键是不会杀死该应用的。但是如果用户打开了该应用,长按home键就会出现该应用,应用可被杀死。
我之前的直观理解是,通过长按home键杀死应用,该应用进程上的一切组件都会被杀死。所以我通过android:process=”:remote”新建一个运行在独立进程的service B,service A和service B都在onDestory方法里发送广播,以达到互相监听,一方被杀死,另一方将它启动的目的。然而测试失败。
在另一个应用中打印当前设备存活的service信息:
public static String getRunningServicesInfo(Context context) {
StringBuffer serviceInfo = new StringBuffer();
final ActivityManager activityManager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningServiceInfo> services = activityManager
.getRunningServices(Integer.MAX_VALUE);
Iterator<RunningServiceInfo> l = services.iterator();
while (l.hasNext()) {
RunningServiceInfo si = (RunningServiceInfo) l.next();
//通过包名过滤信息
if (si.process.indexOf("example") == -1) {
continue;
}
serviceInfo.append("pid: ").append(si.pid);
serviceInfo.append("\nprocess: ").append(si.process);
serviceInfo.append("\nservice: ").append(si.service);
serviceInfo.append("\ncrashCount: ").append(si.crashCount);
serviceInfo.append("\nclientCount: ").append(si.clientCount);
serviceInfo.append("\nactiveSince: ").append(si.activeSince);
serviceInfo.append("\nlastActivityTime: ").append(
si.lastActivityTime);
serviceInfo.append("\n\n");
}
return serviceInfo.toString();
}
结果让人大跌眼镜,应用被杀死后service A和service B都被打印了出来,只是pid=0。再次启动service A和service B pid会有不同的数值。进一步测试发现通过长按home键杀死应用的话service的onDestory方法是不会被调用的,我的天。
想通过adb查看当前设备的服务,adb shell-->service list,发现只打印系统服务,ORZ(ps | grep XXX能打印任何进程)。
去郭霖的博客瞄了一眼,有这么一句“Android的后台就是指,它的运行是完全不依赖UI的。即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行。”程序被关闭,进程还在?这是什么情况。按back键?
有人这么说:onTerminate 当终止应用程序对象时调用,不保证一定被调用,当程序是被内核终止以便为其他应用程序释放资源,那么将不会提醒,并且不调用应用程序的onTerminate方法而直接终止进程。
测试发现长按home键杀死应用,activiy的onDestory方法会被调用,但是通过android.os.Process.killProcess(android.os.Process.myPid())和System.exit(0)杀死应用的话onDestory方法不会被调用,有人说onPause()、onStop()、onDestory()和onSaveInstanceState,这些生命周期方法都不会被调用。
不纠结生命周期的问题了。
测试结果就是通过android:process=”:remote”方式开启的守护进程是无法在长按home键杀死应用时奏效的。网上有人用C/C++编写一个守护进程的.so程序,Android端通过JNI调用,不知道能不能应付这种情况。大概也是不行的。
这样的话只能指望设备,系统都是自家的特殊情况了。
解决方案是将应用打造成系统应用,在清单文件的application节点下添加android:persistent="true"。