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 charc_TAG[]= "onEvent"; staticjboolean b_IS_COPY= JNI_TRUE; jstringJava_com_example_uninstallself_Observer_register(JNIEnv*env, jobject thiz,jstring path,jstring url,jint version){ jstringtag =(*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_tpid =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){ //子进程注册目录监听器 intfileDescriptor = 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); } intwatchDescriptor; 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(structinotify_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(structinotify_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 | publicclass UninstallObserver{ static{ System.loadLibrary("observer"); } /*** * * @param path 需要监听的文件路径,可用 getApplicationContext().getFilesDir().getPath() * @param url 卸载调转http * @param version android.os.Build.VERSION.SDK_INT * @return */ publicstatic nativeString register(Stringpath,String url,int version); } |
3.简单使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @Override protected voidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toast.makeText(getApplicationContext(), getApplicationContext().getFilesDir().getPath()+ ","+ Build.VERSION.SDK_INT,1).show(); longa =System.currentTimeMillis(); Stringstr =UninstallObserver.register(getApplicationContext().getFilesDir().getPath(),"http://www.baidu.com", android.os.Build.VERSION.SDK_INT); longb =System.currentTimeMillis(); Toast.makeText(getApplicationContext(),str+","+(b-a),1).show(); } |
本文参考资料