转载:http://blog.csdn.net/jimmylopez/article/details/41015337#comments
最近看到很多android应用卸载之后,都会弹出一个网页来填写反馈。
参考了http://www.cnblogs.com/zealotrouge/archive/2013/09/24/3182617.html上的方法,我也做了一个。现把代码展示出来。
每次接收到进程中断的消息时,父进程会通过handler通知到子进程,在子进程1中fork一个子进程2,子进程2会sleep1秒,1秒过后判断data/data/下的数据是否存在,从而区分是被其他安全软件kill掉了还是被卸载了。
由于某些手机会直接kill掉子进程1,所以才在子进程1中再fork出子进程2。
- <pre name="code" class="java">#include "apkObserver.h"
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- static jboolean isCopy = JNI_TRUE;
- static char* rtn;
- static char* url;
- static char* action;
- static jboolean isAvailable;
- static jstring s_Searial;
- static int ok = -1;
- static const char OBSERVER_DIR[] = "/data/data/com.xxx.xxx";
- void handler(int signo) {
- if (-1 != ok) {
- pid_t pid;
- pid = fork();
- if (0 == pid) {
- LOG_INFO("Jimmy", "FORK");
- sleep(1);
- int lockFileDescriptor = open(OBSERVER_DIR, O_RDONLY);
- if (lockFileDescriptor == -1) {
- LOG_INFO("Jimmy", "EXIT");
- //已被卸载,跳出反馈页面
- if (isAvailable) {
- if (s_Searial == NULL) {
- execlp("am", "am", "start", "-n", action, "-a",
- "android.intent.action.VIEW", "-d", url,
- (char *) NULL);
- } else {
- execlp("am", "am", "start", "--user", rtn, "-a",
- "android.intent.action.VIEW", "-n", action, "-d",
- url, (char *) NULL);
- }
- } else {
- if (s_Searial == NULL) {
- execlp("am", "am", "start", "-a",
- "android.intent.action.VIEW", "-d", url,
- (char *) NULL);
- } else {
- execlp("am", "am", "start", "--user", rtn, "-a",
- "android.intent.action.VIEW", "-d", url,
- (char *) NULL);
- }
- }
- }else{
- LOG_INFO("Jimmy", "RESTART");
- //发送intent把service重新启动起来
- if (s_Searial == NULL) {
- execlp("am", "am", "startservice", "-n",
- "com.xxx.xxx/com.xxx.service.xxx",
- (char *) NULL);
- } else {
- execlp("am", "am", "startservice", "--user", rtn, "-n",
- "com.xxx.xxx/com.xxx.service.xxx",
- (char *) NULL);
- }
- }
- }else if(pid < 0){
- LOG_INFO("Jimmy", "FORK ERROR");
- exit(-1);
- }else{
- exit(0);
- }
- }
- }
- JNIEXPORT
- int JNICALL
- Java_com_xxx_xxx_MyApkObserver_init(JNIEnv *env, jobject obj,
- jstring userSerial, jstring intentURL, jboolean isAvail,
- jstring intentAction) {
- s_Searial = userSerial;
- isAvailable = isAvail;
- if (userSerial != NULL) {
- rtn = (*env)->GetStringUTFChars(env, userSerial, &isCopy);
- }
- if (intentURL != NULL) {
- url = (*env)->GetStringUTFChars(env, intentURL, &isCopy);
- }
- if (isAvail && intentAction != NULL) {
- action = (*env)->GetStringUTFChars(env, intentAction, &isCopy);
- }
- pid_t pp = getpid();
- pid_t pid;
- pid = fork();
- if (0 == pid) {
- signal(SIGCHLD, handler);
- ptrace(PTRACE_ATTACH, pp, NULL, NULL);
- wait(NULL);
- ptrace(PTRACE_CONT, pp, NULL, NULL);
- ok = 1;
- pause();
- }else if(pid < 0){
- LOG_INFO("Jimmy", "MAIN FORK ERROR");
- exit(-1);
- }
- }
- #ifdef __cplusplus
- }
- #endif