这是一个偶尔由github issue里得到的方案,我还没机会运到实际项目上。希望将来也用不到,暂且记下。
首先来看原理
Android系统中(5.0及以上未验证是否有改变)当前进程(Process)fork出来的子进程,被系统认为是两个不同的进程。当父进程被杀死的时候,子进程仍然可以存活,并不受影响。
然后来看实现步骤
用C编写守护进程(即子进程),守护进程做的事情就是循环检查目标进程是否存在,不存在则启动它。
在NDK环境中将1中编写的C代码编译打包成可执行文件(BUILD_EXECUTABLE)。
主进程启动时将守护进程放入私有目录下,赋予可执行权限,启动它即可。
最后是相关代码片段
- 主函数包含死循环,调用watch()函数循环检查目标是否存在,不存在则调用restart_target()函数启动它,其中pid参数为目标进程的pid,在Android层可以很简单的获得。
- watch()函数。Linux中所有进程在/proc/目录都会有对应的进程目录,例如对于pid为1234的进程,将存在/proc/1234/目录。检查此目录是否存在即可确定目标进程是否存在。
- restart_target()函数。使用Android系统的"am startservice"命令去启动目标服务。其他参数的含义请自行Google。
- 以上就是守护进程的主体部分,接下来使用NDK将其编译打包成可执行文件。以下是Android.mk配置文件内容。
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := watchdog.c
LOCAL_MODULE := watchdog
LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
LOCAL_LDLIBS := -llog
include $(BUILD_EXECUTABLE)
- 完成守护进程的编写后,接下来就是使用它。在Android程序运行时将它放到某个可赋予可执行权限的目录,比如私有目录下的files文件夹内。然后调用shell命令赋予它可执行权限并启动它。
实际的操作过程中如何保证守护进程的唯一性,就留给大家自己去探索吧。
目前提到的在Android-Service层的尝试都会失败,你再怎么设置,系统的控制权限永远都会比你高,被系统杀死只是时间问题。以上方法可实现守护某进程的目的,进而达到服务常驻后台的效果。