Android应用如何监听自己是否被卸载及卸载反馈功能的实现(第二版)

来源:互联网 发布:心脏支架 知乎 编辑:程序博客网 时间:2024/04/18 15:49

转载:http://www.cnblogs.com/zealotrouge/p/3159772.html 

昨天发了一篇有关监听自己是否被卸载和卸载反馈功能实现的博客,地址如下:http://www.cnblogs.com/zealotrouge/p/3157126.html,发出去后收到几位热心网友的建议,在此特别感谢@cccode @泡泡糖 @Alexia(minmin) @0x00.pl ,你们的建议就是我前进的动力。

  昨天的技术方案有一个硬伤,就是每1s就需要轮询目录是否存在,对资源消耗较大,第二版将会解决这一问题。思路是今天想到了一个Android自API1就有的一个类FileObserver,这个类用于监听某个文件的变化状态,如果是目录,这个类还可以监听其子目录及子目录文件的变化状态,通过阅读FileObserver源码,发现其实现利用了Linux内核中一个重要的机制inotify,它是一个内核用于通知用户空间程序文件系统变化的机制,详情可参考http://en.wikipedia.org/wiki/Inotify,里面对inotify有比较详细的说明。

  使用inotify的好处就在于不需要每1s的轮询,这样就不会无谓地消耗系统资源,使用inotify时会用read()方法阻塞进程,直到收到IN_DELETE通知,此时进程重新被唤醒,执行反馈处理流程。

  由于Activity代码和Android.mk文件和第一版并无实质性区别,这里就不贴代码了,直接贴出C端进程的实现代码吧。

核心——native方法头文件:

 

复制代码
 1 /* 头文件begin */ 2 #include <jni.h> 3 #include <stdlib.h> 4 #include <stdio.h> 5 #include <string.h> 6 #include <android/log.h> 7 #include <unistd.h> 8 #include <sys/inotify.h> 9 #include <fcntl.h>10 /* 头文件end */11 12 /* 宏定义begin */13 //清0宏14 #define MEM_ZERO(pDest, destSize) memset(pDest, 0, destSize)15 16 //LOG宏定义17 #define LOG_INFO(tag, msg) __android_log_write(ANDROID_LOG_INFO, tag, msg)18 #define LOG_DEBUG(tag, msg) __android_log_write(ANDROID_LOG_DEBUG, tag, msg)19 #define LOG_WARN(tag, msg) __android_log_write(ANDROID_LOG_WARN, tag, msg)20 #define LOG_ERROR(tag, msg) __android_log_write(ANDROID_LOG_ERROR, tag, msg)21 /* 宏定义end */22 23 #ifndef _Included_main_activity_UninstalledObserverActivity24 #define _Included_main_activity_UninstalledObserverActivity25 #ifdef __cplusplus26 extern "C" {27 #endif28 29 #undef main_activity_UninstalledObserverActivity_MODE_PRIVATE30 #define main_activity_UninstalledObserverActivity_MODE_PRIVATE 0L31 #undef main_activity_UninstalledObserverActivity_MODE_WORLD_READABLE32 #define main_activity_UninstalledObserverActivity_MODE_WORLD_READABLE 1L33 #undef main_activity_UninstalledObserverActivity_MODE_WORLD_WRITEABLE34 #define main_activity_UninstalledObserverActivity_MODE_WORLD_WRITEABLE 2L35 #undef main_activity_UninstalledObserverActivity_MODE_APPEND36 #define main_activity_UninstalledObserverActivity_MODE_APPEND 32768L37 #undef main_activity_UninstalledObserverActivity_MODE_MULTI_PROCESS38 #define main_activity_UninstalledObserverActivity_MODE_MULTI_PROCESS 4L39 #undef main_activity_UninstalledObserverActivity_BIND_AUTO_CREATE40 #define main_activity_UninstalledObserverActivity_BIND_AUTO_CREATE 1L41 #undef main_activity_UninstalledObserverActivity_BIND_DEBUG_UNBIND42 #define main_activity_UninstalledObserverActivity_BIND_DEBUG_UNBIND 2L43 #undef main_activity_UninstalledObserverActivity_BIND_NOT_FOREGROUND44 #define main_activity_UninstalledObserverActivity_BIND_NOT_FOREGROUND 4L45 #undef main_activity_UninstalledObserverActivity_BIND_ABOVE_CLIENT46 #define main_activity_UninstalledObserverActivity_BIND_ABOVE_CLIENT 8L47 #undef main_activity_UninstalledObserverActivity_BIND_ALLOW_OOM_MANAGEMENT48 #define main_activity_UninstalledObserverActivity_BIND_ALLOW_OOM_MANAGEMENT 16L49 #undef main_activity_UninstalledObserverActivity_BIND_WAIVE_PRIORITY50 #define main_activity_UninstalledObserverActivity_BIND_WAIVE_PRIORITY 32L51 #undef main_activity_UninstalledObserverActivity_BIND_IMPORTANT52 #define main_activity_UninstalledObserverActivity_BIND_IMPORTANT 64L53 #undef main_activity_UninstalledObserverActivity_BIND_ADJUST_WITH_ACTIVITY54 #define main_activity_UninstalledObserverActivity_BIND_ADJUST_WITH_ACTIVITY 128L55 #undef main_activity_UninstalledObserverActivity_CONTEXT_INCLUDE_CODE56 #define main_activity_UninstalledObserverActivity_CONTEXT_INCLUDE_CODE 1L57 #undef main_activity_UninstalledObserverActivity_CONTEXT_IGNORE_SECURITY58 #define main_activity_UninstalledObserverActivity_CONTEXT_IGNORE_SECURITY 2L59 #undef main_activity_UninstalledObserverActivity_CONTEXT_RESTRICTED60 #define main_activity_UninstalledObserverActivity_CONTEXT_RESTRICTED 4L61 #undef main_activity_UninstalledObserverActivity_RESULT_CANCELED62 #define main_activity_UninstalledObserverActivity_RESULT_CANCELED 0L63 #undef main_activity_UninstalledObserverActivity_RESULT_OK64 #define main_activity_UninstalledObserverActivity_RESULT_OK -1L65 #undef main_activity_UninstalledObserverActivity_RESULT_FIRST_USER66 #define main_activity_UninstalledObserverActivity_RESULT_FIRST_USER 1L67 #undef main_activity_UninstalledObserverActivity_DEFAULT_KEYS_DISABLE68 #define main_activity_UninstalledObserverActivity_DEFAULT_KEYS_DISABLE 0L69 #undef main_activity_UninstalledObserverActivity_DEFAULT_KEYS_DIALER70 #define main_activity_UninstalledObserverActivity_DEFAULT_KEYS_DIALER 1L71 #undef main_activity_UninstalledObserverActivity_DEFAULT_KEYS_SHORTCUT72 #define main_activity_UninstalledObserverActivity_DEFAULT_KEYS_SHORTCUT 2L73 #undef main_activity_UninstalledObserverActivity_DEFAULT_KEYS_SEARCH_LOCAL74 #define main_activity_UninstalledObserverActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L75 #undef main_activity_UninstalledObserverActivity_DEFAULT_KEYS_SEARCH_GLOBAL76 #define main_activity_UninstalledObserverActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L77 78 /*79  * Class:     main_activity_UninstalledObserverActivity80  * Method:    init81  * Signature: ()V82  */83 JNIEXPORT void JNICALL Java_main_activity_UninstalledObserverActivity_init(JNIEnv *, jobject);84 85 #ifdef __cplusplus86 }87 #endif88 #endif
复制代码

 

核心——native方法实现:

 

复制代码
 1 /* 头文件begin */ 2 #include "main_activity_UninstalledObserverActivity.h" 3 /* 头文件end */ 4  5 #ifdef __cplusplus 6 extern "C" { 7 #endif 8  9 /* 内全局变量begin */10 static char c_TAG[] = "UninstalledObserverActivity.init";11 static jboolean b_IS_COPY = JNI_TRUE;12 /* 内全局变量 */13 14 /*15  * Class:     main_activity_UninstalledObserverActivity16  * Method:    init17  * Signature: ()V18  */19 JNIEXPORT void JNICALL Java_main_activity_UninstalledObserverActivity_init(JNIEnv *env, jobject obj)20 {21     jstring tag = (*env)->NewStringUTF(env, c_TAG);22 23     //初始化log24     LOG_DEBUG((*env)->GetStringUTFChars(env, tag, &b_IS_COPY)25             , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "init OK"), &b_IS_COPY));26 27     //fork子进程,以执行轮询任务28     pid_t pid = fork();29     if (pid < 0)30     {31         //出错log32         LOG_ERROR((*env)->GetStringUTFChars(env, tag, &b_IS_COPY)33                 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "fork failed !!!"), &b_IS_COPY));34     }35     else if (pid == 0)36     {37         //子进程注册"/data/data/pym.test.uninstalledobserver"目录监听器38         int fileDescriptor = inotify_init();39         if (fileDescriptor < 0)40         {41             LOG_DEBUG((*env)->GetStringUTFChars(env, tag, &b_IS_COPY)42                     , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "inotify_init failed !!!"), &b_IS_COPY));43 44              exit(1);45         }46 47         int watchDescriptor;48         watchDescriptor = inotify_add_watch(fileDescriptor, "/data/data/pym.test.uninstalledobserver", IN_DELETE);49         if (watchDescriptor < 0)50         {51             LOG_DEBUG((*env)->GetStringUTFChars(env, tag, &b_IS_COPY)52                     , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "inotify_add_watch failed !!!"), &b_IS_COPY));53 54             exit(1);55         }56 57         //分配缓存,以便读取event,缓存大小=一个struct inotify_event的大小,这样一次处理一个event58         void *p_buf = malloc(sizeof(struct inotify_event));59         if (p_buf == NULL)60         {61             LOG_DEBUG((*env)->GetStringUTFChars(env, tag, &b_IS_COPY)62                     , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "malloc failed !!!"), &b_IS_COPY));63 64             exit(1);65         }66         //开始监听67         LOG_DEBUG((*env)->GetStringUTFChars(env, tag, &b_IS_COPY)68                     , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "start observer"), &b_IS_COPY));69         size_t readBytes = read(fileDescriptor, p_buf, sizeof(struct inotify_event));70 71         //read会阻塞进程,走到这里说明收到目录被删除的事件,注销监听器72         free(p_buf);73         inotify_rm_watch(fileDescriptor, IN_DELETE);74 75         //目录不存在log76         LOG_DEBUG((*env)->GetStringUTFChars(env, tag, &b_IS_COPY)77                     , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "uninstalled"), &b_IS_COPY));78 79         //执行命令am start -a android.intent.action.VIEW -d http://shouji.360.cn/web/uninstall/uninstall.html80         execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d", "http://shouji.360.cn/web/uninstall/uninstall.html", (char *)NULL);81     }82     else83     {84         //父进程直接退出,使子进程被init进程领养,以避免子进程僵死85     }86 }87 88 #ifdef __cplusplus89 }90 #endif
复制代码
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 同学们不和我玩怎么办 懒癌和拖延症怎么办 有严重的拖延症怎么办 有拖延症的人怎么办 10多天月经不停怎么办 20多天月经不停怎么办 月经来了十几天不停怎么办 例假20多天不停怎么办 苹果6dns被劫持怎么办 工地欠工资不给怎么办 买的狗得病了怎么办 剖腹产9天刀口痒怎么办 剖腹产6天刀口痒怎么办 剖腹产2年刀口痒怎么办 破腹产9天刀口痒怎么办 破腹产7天刀口痒怎么办 剖腹产8天伤口痒怎么办 刨腹产9天刀口痒怎么办 破腹产8天刀口痒怎么办 二胎刀口1.1mm薄怎么办 土豪养成记2闪退怎么办 爱上不该爱的人怎么办? 有妇之夫爱上我,怎么办 全身起疙瘩很痒怎么办 怀孕了肚子很痛怎么办 月经来肚子疼的厉害怎么办 孕妇9个月肚子疼怎么办 斗鱼身上长白点怎么办 8个月宝宝肚子疼怎么办 1岁半宝宝肚子痛怎么办 3岁宝宝肚子疼怎么办啊 吃的太辣肚子疼怎么办 2岁半宝宝肚子疼怎么办 2岁宝宝肚子痛哭怎么办 怀孕3个月拉肚子怎么办 一岁宝宝消化不良拉肚子怎么办 后背长好多痘痘怎么办 身上起疹子很痒怎么办 背上长好多痘痘怎么办 月经两三个月不来怎么办 来月经很少是褐色的怎么办