zoukankan      html  css  js  c++  java
  • Android应用如何监听自己是否被卸载及卸载反馈功能的实现(第二版)

      昨天发了一篇有关监听自己是否被卸载和卸载反馈功能实现的博客,地址如下: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_UninstalledObserverActivity
    24 #define _Included_main_activity_UninstalledObserverActivity
    25 #ifdef __cplusplus
    26 extern "C" {
    27 #endif
    28 
    29 #undef main_activity_UninstalledObserverActivity_MODE_PRIVATE
    30 #define main_activity_UninstalledObserverActivity_MODE_PRIVATE 0L
    31 #undef main_activity_UninstalledObserverActivity_MODE_WORLD_READABLE
    32 #define main_activity_UninstalledObserverActivity_MODE_WORLD_READABLE 1L
    33 #undef main_activity_UninstalledObserverActivity_MODE_WORLD_WRITEABLE
    34 #define main_activity_UninstalledObserverActivity_MODE_WORLD_WRITEABLE 2L
    35 #undef main_activity_UninstalledObserverActivity_MODE_APPEND
    36 #define main_activity_UninstalledObserverActivity_MODE_APPEND 32768L
    37 #undef main_activity_UninstalledObserverActivity_MODE_MULTI_PROCESS
    38 #define main_activity_UninstalledObserverActivity_MODE_MULTI_PROCESS 4L
    39 #undef main_activity_UninstalledObserverActivity_BIND_AUTO_CREATE
    40 #define main_activity_UninstalledObserverActivity_BIND_AUTO_CREATE 1L
    41 #undef main_activity_UninstalledObserverActivity_BIND_DEBUG_UNBIND
    42 #define main_activity_UninstalledObserverActivity_BIND_DEBUG_UNBIND 2L
    43 #undef main_activity_UninstalledObserverActivity_BIND_NOT_FOREGROUND
    44 #define main_activity_UninstalledObserverActivity_BIND_NOT_FOREGROUND 4L
    45 #undef main_activity_UninstalledObserverActivity_BIND_ABOVE_CLIENT
    46 #define main_activity_UninstalledObserverActivity_BIND_ABOVE_CLIENT 8L
    47 #undef main_activity_UninstalledObserverActivity_BIND_ALLOW_OOM_MANAGEMENT
    48 #define main_activity_UninstalledObserverActivity_BIND_ALLOW_OOM_MANAGEMENT 16L
    49 #undef main_activity_UninstalledObserverActivity_BIND_WAIVE_PRIORITY
    50 #define main_activity_UninstalledObserverActivity_BIND_WAIVE_PRIORITY 32L
    51 #undef main_activity_UninstalledObserverActivity_BIND_IMPORTANT
    52 #define main_activity_UninstalledObserverActivity_BIND_IMPORTANT 64L
    53 #undef main_activity_UninstalledObserverActivity_BIND_ADJUST_WITH_ACTIVITY
    54 #define main_activity_UninstalledObserverActivity_BIND_ADJUST_WITH_ACTIVITY 128L
    55 #undef main_activity_UninstalledObserverActivity_CONTEXT_INCLUDE_CODE
    56 #define main_activity_UninstalledObserverActivity_CONTEXT_INCLUDE_CODE 1L
    57 #undef main_activity_UninstalledObserverActivity_CONTEXT_IGNORE_SECURITY
    58 #define main_activity_UninstalledObserverActivity_CONTEXT_IGNORE_SECURITY 2L
    59 #undef main_activity_UninstalledObserverActivity_CONTEXT_RESTRICTED
    60 #define main_activity_UninstalledObserverActivity_CONTEXT_RESTRICTED 4L
    61 #undef main_activity_UninstalledObserverActivity_RESULT_CANCELED
    62 #define main_activity_UninstalledObserverActivity_RESULT_CANCELED 0L
    63 #undef main_activity_UninstalledObserverActivity_RESULT_OK
    64 #define main_activity_UninstalledObserverActivity_RESULT_OK -1L
    65 #undef main_activity_UninstalledObserverActivity_RESULT_FIRST_USER
    66 #define main_activity_UninstalledObserverActivity_RESULT_FIRST_USER 1L
    67 #undef main_activity_UninstalledObserverActivity_DEFAULT_KEYS_DISABLE
    68 #define main_activity_UninstalledObserverActivity_DEFAULT_KEYS_DISABLE 0L
    69 #undef main_activity_UninstalledObserverActivity_DEFAULT_KEYS_DIALER
    70 #define main_activity_UninstalledObserverActivity_DEFAULT_KEYS_DIALER 1L
    71 #undef main_activity_UninstalledObserverActivity_DEFAULT_KEYS_SHORTCUT
    72 #define main_activity_UninstalledObserverActivity_DEFAULT_KEYS_SHORTCUT 2L
    73 #undef main_activity_UninstalledObserverActivity_DEFAULT_KEYS_SEARCH_LOCAL
    74 #define main_activity_UninstalledObserverActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L
    75 #undef main_activity_UninstalledObserverActivity_DEFAULT_KEYS_SEARCH_GLOBAL
    76 #define main_activity_UninstalledObserverActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L
    77 
    78 /*
    79  * Class:     main_activity_UninstalledObserverActivity
    80  * Method:    init
    81  * Signature: ()V
    82  */
    83 JNIEXPORT void JNICALL Java_main_activity_UninstalledObserverActivity_init(JNIEnv *, jobject);
    84 
    85 #ifdef __cplusplus
    86 }
    87 #endif
    88 #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_UninstalledObserverActivity
    16  * Method:    init
    17  * Signature: ()V
    18  */
    19 JNIEXPORT void JNICALL Java_main_activity_UninstalledObserverActivity_init(JNIEnv *env, jobject obj)
    20 {
    21     jstring tag = (*env)->NewStringUTF(env, c_TAG);
    22 
    23     //初始化log
    24     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         //出错log
    32         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的大小,这样一次处理一个event
    58         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         //目录不存在log
    76         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.html
    80         execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d", "http://shouji.360.cn/web/uninstall/uninstall.html", (char *)NULL);
    81     }
    82     else
    83     {
    84         //父进程直接退出,使子进程被init进程领养,以避免子进程僵死
    85     }
    86 }
    87 
    88 #ifdef __cplusplus
    89 }
    90 #endif
  • 相关阅读:
    2
    异常处理
    接口
    抽象与多态
    关联关系
    9-13
    数据类型转换
    Day3
    对象和类
    MyEclipse导入现成项目出现小红叉错误
  • 原文地址:https://www.cnblogs.com/zealotrouge/p/3159772.html
Copyright © 2011-2022 走看看