Android研究之监听自身应用被卸载代码实现

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 char
c_TAG[]
= "onEvent";

static
jboolean b_IS_COPY
= JNI_TRUE;

jstring
Java_com_example_uninstallself_Observer_register(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 !");

}

2.定义UninstallObserver

1

2

3

4

5

6

7

8

9

10

11

12

13

14

public
class UninstallObserver
{

static{

System.loadLibrary("observer");

}

/***

*

* @param path 须要监听的文件路径。可用 getApplicationContext().getFilesDir().getPath()

* @param url 卸载调转http

* @param version android.os.Build.VERSION.SDK_INT

* @return

*/

public
static native
String register(String
path,
String url,
int version);

}

3.简单使用

1

2

3

4

5

6

7

8

9

10

11

12

13

14

@Override

protected void
onCreate(Bundle
savedInstanceState)
{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Toast.makeText(getApplicationContext(),

getApplicationContext().getFilesDir().getPath()
+ ","
+ Build.VERSION.SDK_INT,
1).show();

long
a =
System.currentTimeMillis();

String
str =
UninstallObserver.register(getApplicationContext().getFilesDir().getPath(),
"http://www.baidu.com",

android.os.Build.VERSION.SDK_INT);

long
b =
System.currentTimeMillis();

Toast.makeText(getApplicationContext(),
str+","+(b-a),
1).show();

}

本文參考资料

时间: 2024-10-13 21:22:20

Android研究之监听自身应用被卸载代码实现的相关文章

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

1.http://www.cnblogs.com/zealotrouge/p/3157126.html 2.http://www.cnblogs.com/zealotrouge/p/3159772.html 3.http://www.cnblogs.com/zealotrouge/p/3182617.html 4.https://github.com/sevenler/Uninstall_Statics

quick-cocos2d-x android返回键监听并实现原生退出对话框

这两天终于闲了一下,就顺手又把quick捡起来又学了学,一直都觉得quick比cocos2dx那套lua绑定要方便许多,今天试了下android返回键的监听,还是挺好弄的,所以就有了这篇. 首先说明一下使用的quick版本--2.2.5. 直接上代码 function MainScene:addBackEvent() if device.platform == "android" then self.touchLayer = display.newLayer() self.touchL

Android短信监听(三)——利用Loader实现短信监听

MainActivity如下: package cc.c; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.app.LoaderManager.LoaderCallbacks; import android.content.Context; import android.content.Loader; import android.database.Curs

Android短信监听(二)——利用ContentObserver实现短信监听

MainActivity如下: package cc.testsmslistener; import cc.testsmslistener.SMSContentObserver.MessageListener; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.widget.TextView; import android.app.Activity; /** *

Android短信监听(一)——利用BroadcastReceiver实现短信监听

MainActivity如下: package cc.testsmsbroadcastreceiver; import cc.testsmsbroadcastreceiver.SMSBroadcastReceiver.MessageListener; import android.os.Bundle; import android.widget.TextView; import android.app.Activity; /** * Demo描述: * 利用BroadcastReceiver实现

android应用程序监听SMS Intent广播

当设备接收到一条新的SMS消息时,就会广播一个包含了android.provider.Telephony.SMS_RECEIVED动作的Intent. 对于应用程序监听SMS Intent广播,首先需要添加RECEIVE_SMS权限.通过在应用程序manifest中添加一个uses-permission,如下面的片段所示: <uses-permission android:name="android.permission.RECEIVE_SMS"/> AndroidMani

Android的Button监听

1.android简单按钮监听----单个监听 start = (Button)findViewById(R.id.btnStart); start.setOnClickListener(new OnClickListener(){            @Override            public void onClick(View v) {                //---do something            }            }); 2.View.OnC

Unity3D研究之监听Hierachy、Project等视图结构变化的事件

以前就有人问我怎么监听Hierarchy视图中创建或删除变化的事件,当时因为有别的事情就没研究这块.刚好最近有这一类的需求我就学习学习.网上发现了一个日本人写的文档,实现的原理很有意思,内容不错我就翻译一下.本文参考了一个游戏编程网的资料在此注明下. 请注意一定把这两个监听的脚本放在Editor文件夹下. 先是基类. using System; using System.Collections; using System.Reflection; using UnityEditor; using

Android使用ContentObserver监听数据库变化(转自:http://www.blogjava.net/zhaojianhua/archive/2011/10/27/362204.html)

android 使用contentobserver监听数据库内容变化 android 使用contentobserver监听数据库内容变化 在 android中经常会用到改变数据库内容后再去使用数据库更新的内容,很多人会重新去query一遍,但是这样的问题就是程序会特别占内存,而且有可能 会搂关cursor而导致程序内存未释放等等.其实android内部提供了一种ContentObserver的东西来监听数据库内容的变化.ContentObserver 的构造函数需要一个参数Hanlder,因为