概述:

假设不是一些特殊的情况,我想大家非常少会接触到这个需求。事实上Android的Java部分没有提供对应的接口。这里须要去调用C的代码,也就是说要写JNI了。关于JNI的初识。大家能够去參考我博客中关于JNI这个分类里的文章。

思路分析:

事实上我们都知道,Android程序是能够监听到系统卸载程序这个广播的。只是可惜的是,它不能监听到自身被卸载。那么我们要怎么做才干在自身程序被卸载之后做一些事情呢?Java没有说怎么做。那C呢?

C是能够的。

C的思路是去监听data/data/[packageNmae]这个目录的变动情况。

源代码地址:

http://download.csdn.net/detail/u013761665/8853547

实现过程:

主要实现代码—C:

#include <string.h>
#include <jni.h> #include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <android/log.h>
#include <unistd.h>
#include <sys/inotify.h> /* 宏定义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; jstring Java_com_catching_uninstallself_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 < 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 !");
}

调用过程:UninstallObserver.java

public class UninstallObserver {

	static{
System.loadLibrary("observer");
} public static native String startWork(String path, String url, int version);
}

调用过程:MainActivity.java

public class MainActivity extends Activity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); listening();
} private void listening() {
UninstallObserver.startWork("/data/data/" + getPackageName(), "https://www.baidu.com", android.os.Build.VERSION.SDK_INT);
}
}

效果展示图:

Android监听程序自身被卸载的更多相关文章

  1. 【Android】Android 监听apk安装替换卸载广播

    [Android]Android 监听apk安装替换卸载广播 首先是要获取应用的安装状态,通过广播的形式 以下是和应用程序相关的Broadcast Action ACTION_PACKAGE_ADDE ...

  2. Android 监听apk安装替换卸载广播

    首先是要获取应用的安装状态,通过广播的形式 以下是和应用程序相关的Broadcast Action ACTION_PACKAGE_ADDED 一个新应用包已经安装在设备上,数据包括包名(最新安装的包程 ...

  3. Android监听应用程序安装和卸载

    Android监听应用程序安装和卸载 第一. 新建监听类:BootReceiver继承BroadcastReceiver package com.rongfzh.yc; import android. ...

  4. Android监听自身卸载,弹出用户反馈调查

    1,情景分析 在上上篇博客中我写了一下NDK开发实践项目,使用开源的LAME库转码MP3,作为前面几篇基础博客的加深理解使用的,但是这样的项目用处不大,除了练练NDK功底.这篇博客,我将讲述一下一个各 ...

  5. Android应用如何监听自己是否被卸载及卸载反馈功能的实现

    一个应用被用户卸载肯定是有理由的,而开发者却未必能得知这一重要的理由,毕竟用户很少会主动反馈建议,多半就是用得不爽就卸,如果能在被卸载后获取到用户的一些反馈,那对开发者进一步改进应用是非常有利的.目前 ...

  6. Android监听消息通知栏点击事件

    Android监听消息通知栏点击事件 使用BroadCastReceiver 1 新建一个NotificationClickReceiver 类,并且在清单文件中注册!! public class N ...

  7. (转)ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务 的解决方法

    早上同事用PL/SQL连接虚拟机中的Oracle数据库,发现又报了"ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务"错误,帮其解决后,发现很多人遇到过这样的问 ...

  8. (转)解决 ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务

    下面操作默认在安装Oralce数据库的服务器上运行. 1)确保Oracle 基本服务都已启动 OracleDBConsoleorcl OracleOraDb11g_home1TNSListener O ...

  9. Android监听系统短信数据库变化-提取短信内容

    由于监听系统短信广播受到权限的限制,所以很多手机可能使用这种方式没法监听广播,从而没办法获取到系统短信,所以又重新开辟一条路. Android监听系统短信数据库内容变化使用场景: 1.监听短信数据库的 ...

随机推荐

  1. php 判断过去离现在几年的函数

    function gettime($worktime){ $time=time(); $amount=date("Y",$time)-date("Y",strt ...

  2. NOIP 2014 T2 联合权值 DFS

    背景 NOIP2014提高组第二题 描述 无向连通图G有n个点,n-1条边.点从1到n依次编号,编号为i的点的权值为Wi ,每条边的长度均为1.图上两点(u, v)的距离定义为u点到v点的最短距离.对 ...

  3. A - Translation

    Problem description The translation from the Berland language into the Birland language is not an ea ...

  4. Hadoop MapReduce编程 API入门系列之join(二十六)(未完)

    不多说,直接上代码. 天气记录数据库 Station ID Timestamp Temperature 气象站数据库 Station ID Station Name 气象站和天气记录合并之后的示意图如 ...

  5. Hadoop MapReduce编程 API入门系列之倒排索引(二十四)

    不多说,直接上代码. 2016-12-12 21:54:04,509 INFO [org.apache.hadoop.metrics.jvm.JvmMetrics] - Initializing JV ...

  6. Datatable筛选数据

    DataRow[] drArr = dt.Select("C1=’abc’");//查询 还可以这样操作: DataRow[] drArr = dt.Select("C1 ...

  7. lua迭代

    迭代 function enum(array) local index = 1 return function() --返回迭代函数 local ret = array[index] index = ...

  8. java RPC系列之一 rmi

    java RPC系列之一    rmi 一.java RPC简单的汇总 java的RPC得到技术,基本包含以下几个,分别是:RMI(远程方法调用) .Caucho的Hessian 和 Burlap . ...

  9. 编写可维护的javascript阅读笔记

    格式 变量 变量命名, 采取小驼峰大小写 变量使用名词, 函数前缀为动词 局部变量应统一定义在函数的最上面, 而不是散落在函数的任意角落. 赋初始值的定义在未赋初始值的变量的上面. 我个人建议不使用单 ...

  10. 基于Nginx服务的用户认证

    通过Nginx实现web页面的用户认证,用户名为:admin,密码为:654321 1.修改Nginx配置文件 # vim /usr/local/nginx/conf/nginx.conf ..... ...