在android app开发中,有的时候会有这样的需求,就是当用户卸载了我们的app的时候,如果可以搜集用户的反馈信息,那样是极好的,今天带大家手把手实现这样的功能,先说下原理:我们的app在安装的时候会在/data/data/报名,下生成这样的文件夹,一旦我们的应用被卸载,那么该文件夹同样会被移除,因此,我们可以通过利用底层c代码不断地查询该文件夹是否来存在,来判断app是否被卸载。

声明native方法


这里创建一个NativeClass来生命一个本地方法,代码如下:

package com.example.uninstallprompt;public class NativeClass {public native String init();}

生成.h头文件

在生成头文件之前,首先需要生成.class文件

生成.h头文件

注意这里的格式是:javah -classpath src路径 -jni 包名.类名称
此时会在src路径下生成.h头文件

内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */#include /* Header for class com_example_uninstallprompt_NativeClass */#ifndef _Included_com_example_uninstallprompt_NativeClass#define _Included_com_example_uninstallprompt_NativeClass#ifdef __cplusplusextern "C" {#endif/* * Class:     com_example_uninstallprompt_NativeClass * Method:    init * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_example_uninstallprompt_NativeClass_init  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif

编写c代码

在android工程中新建一个jni目录,并且在该目录下新建一个uninstall-jni.c文件,将刚才生成的.h文件的内容拷贝进来。并且将生成的"com_example_uninstallprompt_NativeClass.h"文件拷贝到该文件夹下。
uninstall-jni.c内容如下:

#include #include #include #include #include #include #include #include "com_example_uninstallprompt_NativeClass.h"/* 宏定义begin *///清0宏#define MEM_ZERO(pDest, destSize) memset(pDest, 0, destSize)#define LOG_TAG "onEvent"//LOG宏定义#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, fmt, ##args)JNIEXPORT jstring JNICALL Java_com_example_uninstallprompt_NativeClass_init(JNIEnv* env, jobject thiz) {//初始化logLOGD("init start...");//fork子进程,以执行轮询任务pid_t pid = fork();if (pid < 0) {//出错logLOGD("fork failed...");} else if (pid == 0) {//子进程注册"/data/data/com.example.uninstallprompt"目录监听器int fileDescriptor = inotify_init();if (fileDescriptor < 0) {LOGD("inotify_init failed...");exit(1);}int watchDescriptor;watchDescriptor = inotify_add_watch(fileDescriptor,"/data/data/com.example.uninstallprompt", IN_DELETE);LOGD("watchDescriptor=%d",watchDescriptor);if (watchDescriptor < 0) {LOGD("inotify_add_watch failed...");exit(1);}//分配缓存,以便读取event,缓存大小=一个struct inotify_event的大小,这样一次处理一个eventvoid *p_buf = malloc(sizeof(struct inotify_event));if (p_buf == NULL) {LOGD("malloc failed...");exit(1);}//开始监听LOGD("start observer...");size_t readBytes = read(fileDescriptor, p_buf,sizeof(struct inotify_event));//read会阻塞进程,走到这里说明收到目录被删除的事件,注销监听器free(p_buf);inotify_rm_watch(fileDescriptor, IN_DELETE);//目录不存在logLOGD("uninstall");//执行命令am start -a android.intent.action.VIEW -d http://shouji.360.cn/web/uninstall/uninstall.html//execlp(//"am", "am", "start", "-a", "android.intent.action.VIEW", "-d",//"http://shouji.360.cn/web/uninstall/uninstall.html", (char *)NULL);//4.2以上的系统由于用户权限管理更严格,需要加上 --user 0execlp("am", "am", "start", "--user", "0", "-a","android.intent.action.VIEW", "-d", "https://www.baidu.com",(char *) NULL);} else {//父进程直接退出,使子进程被init进程领养,以避免子进程僵死}return (*env)->NewStringUTF(env, "Hello from JNI !");}

这里我在该应用被卸载的时候跳转到百度的主界面。

编写Android.mk文件

在刚才新建的jni目录下新建一个Android.mk文件,内容如下:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE    := uninstall-jniLOCAL_SRC_FILES := uninstall-jni.cLOCAL_C_INCLUDES := $(LOCAL_PATH)/includeLOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -lloginclude $(BUILD_SHARED_LIBRARY)

说明一下:
LOCAL_MODULE := uninstall-jni 表示编译出来的模块,这个模块名称是随意给的,在java文件红引入的时候需要和该名称相同,不过一般和需要编译的.c文件名称保持一致。
LOCAL_SRC_FILES := uninstall-jni.c 表示需要编译的.c文件

编译c代码


可以看到,这里首先进入工程的根目录,然后执行ndk-build编译该工程中Android.mk中声明的c代码。编译完成可以看到在工程中多了如下文件夹和文件。

这里,如果有哪些步骤不是很清楚,或者是不太懂的地方,可以看我的另一篇博客一步一步学习androidNDK编程(hello world)

ok,现在安装以后,在卸载该app的时候,会弹出浏览器自动跳转到百度的主页面。

源码下载
好了,今天就到这里了,希望大家能够喜欢。

欢 迎 关 注 我 的 公 众 号 “编 程 大 全”

专注技术分享,包括Java,python,AI人工智能,Android分享,不定期更新学习视频

更多相关文章

  1. [Android]你不知道的Android进程化(1)--进程信息
  2. Android开发之android中的多进程模式
  3. android 前后台保活 实现定位数据定时上传并展示轨迹 (上)
  4. Android实现自定义铃音
  5. Windows环境下Android(安卓)NDK的开发
  6. Android导出与使用带资源的lib包
  7. Android实现换肤功能(一)
  8. SWIG与JAVA的交互指南一
  9. 使用proguard混淆android代码

随机推荐

  1. Sql Server 2012完全卸载方法 只需8步轻
  2. SQL Server 聚焦存储过程性能优化、数据
  3. SQL查询中需要使用别名问题
  4. sql server2016里面的json功能浅析
  5. SQL Server 2012开窗函数
  6. SQL Server 2012 多表连接查询功能实例代
  7. CentOS 7.3上SQL Server vNext CTP 1.2安
  8. SQLite Delete详解及实例代码
  9. SQL2008 详解直接将XML存入到SQL中
  10. SQL Server存储过程同时返回分页结果集和