Android研究之监听自身应用被卸载代码实现

归志宁无五亩园,读书本意在元元。这篇文章主要讲述Android研究之监听自身应用被卸载代码实现相关的知识,希望能为你提供帮助。
1.通过jni实现函数

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 //LOG宏定义#define LOG_INFO(tag, msg) __android_log_write(ANDROID_LOG_INFO, tag, msg) #define LOG_DEBUG(tag, msg) __android_log_write(ANDROID_LOG_DEBUG, tag, msg)#define LOG_WARN(tag, msg) __android_log_write(ANDROID_LOG_WARN, tag, msg) #define LOG_ERROR(tag, msg) __android_log_write(ANDROID_LOG_ERROR, tag, msg)  /* 内全局变量begin */static char c_TAG[] = "onEvent"; static jboolean b_IS_COPY = JNI_TRUE;   jstring java_com_example_uninstallself_Observer_register(JNIEnv* env,                jobject thiz, jstring path, jstring url, jint version) {         jstring tag = (*env)-> NewStringUTF(env, c_TAG);           //初始化log        LOG_DEBUG((*env)-> GetStringUTFChars(env, tag, & b_IS_COPY),                         (*env)-> GetStringUTFChars(env, (*env)-> NewStringUTF(env, "init OK"),                                        & b_IS_COPY));           //fork子进程。以运行轮询任务         pid_t pid = fork();         if (pid < 0) {                 //出错log                LOG_ERROR((*env)-> GetStringUTFChars(env, tag, & b_IS_COPY),                                 (*env)-> GetStringUTFChars(env,                                                (*env)-> NewStringUTF(env, "fork failed !!!"),                                                 & b_IS_COPY));         } else if (pid == 0) {                 //子进程注冊文件夹监听器                int fileDescriptor = inotify_init();                 if (fileDescriptor < 0) {                        LOG_DEBUG((*env)-> GetStringUTFChars(env, tag, & b_IS_COPY),                                         (*env)-> GetStringUTFChars(env,                                                        (*env)-> NewStringUTF(env,                                                                         "inotify_init failed !!!"), & b_IS_COPY));                           exit(1);                 }                   int watchDescriptor;                   watchDescriptor = inotify_add_watch(fileDescriptor,                                 (*env)-> GetStringUTFChars(env, path, NULL), IN_DELETE);                 if (watchDescriptor < 0) {                         LOG_DEBUG((*env)-> GetStringUTFChars(env, tag, & b_IS_COPY),                                        (*env)-> GetStringUTFChars(env,                                                         (*env)-> NewStringUTF(env,                                                                        "inotify_add_watch failed !!!"),                                                         & b_IS_COPY));                           exit(1);                 }                   //分配缓存。以便读取event。缓存大小=一个struct inotify_event的大小。这样一次处理一个event                 void *p_buf = malloc(sizeof(struct inotify_event));                 if (p_buf == NULL) {                         LOG_DEBUG((*env)-> GetStringUTFChars(env, tag, & b_IS_COPY),                                        (*env)-> GetStringUTFChars(env,                                                         (*env)-> NewStringUTF(env, "malloc failed !!!"),                                                        & b_IS_COPY));                           exit(1);                 }                //開始监听                 LOG_DEBUG((*env)-> GetStringUTFChars(env, tag, & b_IS_COPY),                                (*env)-> GetStringUTFChars(env,                                                 (*env)-> NewStringUTF(env, "start observer"),                                                & b_IS_COPY));                 //read会堵塞进程,                size_t readBytes = read(fileDescriptor, p_buf,                                 sizeof(struct inotify_event));                   //走到这里说明收到文件夹被删除的事件。注销监听器                free(p_buf);                 inotify_rm_watch(fileDescriptor, IN_DELETE);                   //文件夹不存在log                LOG_DEBUG((*env)-> GetStringUTFChars(env, tag, & b_IS_COPY),                                 (*env)-> GetStringUTFChars(env,                                                (*env)-> NewStringUTF(env, "uninstalled"), & b_IS_COPY));                   if (version > = 17) {                         //4.2以上的系统因为用户权限管理更严格,须要加上 --user 0                        execlp("am", "am", "start", "--user", "0", "-a",                                         "android.intent.action.VIEW", "-d",                                        (*env)-> GetStringUTFChars(env, url, NULL), (char *) NULL);                 } else {                        execlp("am", "am", "start", "-a", "android.intent.action.VIEW",                                         "-d", (*env)-> GetStringUTFChars(env, url, NULL),                                        (char *) NULL);                 }                //扩展:能够运行其它shell命令,am(即activity manager),能够打开某程序、服务,broadcast intent,等等           } else {                 //父进程直接退出,使子进程被init进程领养,以避免子进程僵死        }           return (*env)-> NewStringUTF(env, "Hello from JNI !"); }
2.定义UninstallObserver

1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class UninstallObserver {          static{                System.loadLibrary("observer");         }        /***         *        * @param path 须要监听的文件路径。可用 getApplicationContext().getFilesDir().getPath()         * @param url 卸载调转http        * @param version android.os.Build.VERSION.SDK_INT         * @return        */         public static native String register(String path, String url, int version); }
3.简单使用

1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Overrideprotected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);           Toast.makeText(getApplicationContext(),                         getApplicationContext().getFilesDir().getPath() + "," + Build.VERSION.SDK_INT, 1).show();         long a = System.currentTimeMillis();         String str = UninstallObserver.register(getApplicationContext().getFilesDir().getPath(), "http://www.baidu.com",                        android.os.Build.VERSION.SDK_INT);         long b = System.currentTimeMillis();         Toast.makeText(getApplicationContext(), str+","+(b-a), 1).show();   }


【Android研究之监听自身应用被卸载代码实现】本文參考资料





    推荐阅读