调用一个本地函数 由c/c++实现
package com.lapel.catchuninstallself;public class uninstallobserver { static { system.loadlibrary(observer); } /** * * @param path 本地安装apk路径 * @param url 卸载后弹出的页面 * @param version 本机的版本 * @return */ public static native string startwork(string path, string url, int version);}
c/c++实现
/* * copyright (c) 2009 the android open source project * * licensed under the apache license, version 2.0 (the license); * you may not use this file except in compliance with the license. * you may obtain a copy of the license at * * http://www.apache.org/licenses/license-2.0 * * unless required by applicable law or agreed to in writing, software * distributed under the license is distributed on an as is basis, * without warranties or conditions of any kind, either express or implied. * see the license for the specific language governing permissions and * limitations under the license. * */#include #include #include #include #include #include #include #include #include /* 宏定义begin *///清0宏#define mem_zero(pdest, destsize) memset(pdest, 0, destsize)//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;//原包 com.zgy.catchuninstallself----------java_com_zgy_catchuninstallself_uninstallobserver_startwork//现包 com.lapel.catchuninstallselfjstring java_com_lapel_catchuninstallself_uninstallobserver_startwork(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 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 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 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 !);}
android.mk 文件夹
local_path := $(call my-dir)include $(clear_vars)local_module:=observerlocal_src_files:=observer.clocal_c_includes:= $(local_path)/includelocal_ldlibs += -l$(sysroot)/usr/lib -lloginclude $(build_shared_library)
运行后即可生成.so文件
system.loadlibray(observer)://即可完成加载,之后调用本地方法即可