Android 下 JNI 开发

12.C代码打印出日志

 

 

04_卸载之后打开Android浏览器问卷调查-26

fork分叉函数

 

fork分叉(分裂)函数可以创建一个新进程, 并且新创建出来的进程(子进程)拥有创建它的那个进程(父进程)的数据空间, 堆栈资源等的拷贝. 并且相互不影响. (跟fork炸弹原理一样)

 

返回值会返回两次, 但有三种情况:

在父进程中, fork返回新创建子进程的进程ID.大于0

在子进程中, fork返回0.

如果出现错误, fork返回一个负值.

 

 

该功能原理简介

 在程序没有卸载之前,调用C代码,去fork分叉出一个子进程;当程序被卸载时,这个子进程没有被立即关闭。这个子进程需要做的工作是:每一秒去查看/data/data/下是否有当前应用的包名,如果没有,被卸载了,打开浏览器,弹出一个页面,问卷调查用户卸载的原因。

 

实现思路归纳

 

1.声明native方法

2.在C语言中实现,里面去做fork分叉出一个子进程

3.子进程每隔1秒钟监听/data/data/当前包是否卸载

4.如果卸载了,调用Android浏览器

 

 

声明native方法

 直接在压力值项目中做。

 

public native void uninstallListener();

 

 

4.在C语言中实现,里面去做fork分叉出一个子进程,并演示

 

//此方法会创建一个进程,父进程会返回一个值,子进程也会返回一次值.

int state = fork();

if(state > 0){

//当前是父进程

LOGD("parent process=%d",state);

}else if(state == 0){

//当前是子进程

LOGD("sup process=%d",state);

}else{

LOGD("Error");

}

 

 

5.子进程每隔1秒钟监听/data/data/当前包是否卸载

//此方法会创建一个进程,父进程会返回一个值,子进程也会返回一次值.

int state = fork();

if(state > 0){

//当前是父进程

LOGD("parent process=%d",state);

}else if(state == 0){

//当前是子进程

LOGD("sup process=%d",state);

//监听当前应用是否卸载

int isStop = 1;

while(isStop){

//每隔1秒钟判断应用目录是否存在

sleep(1);

//FILE *fopen(const char *, const char *);

FILE* file = fopen("/data/data/ com.atguigu.pressuredemo","r");

if(file == NULL){

//当文件夹没有了,就是被卸载了

LOGD("uninstalled ....");

isStop = 0;

}

}

}else{

LOGD("Error");

}

 

6.C代码调用Android浏览器

 

 

Dos命令行中打开浏览器:

adb shell am start -a android.intent.action.VIEW -d http://www.atguigu.com

 

adb shell am start -a android.intent.action.VIEW -d http://192.168.30.165:8080/uninstall.html

C语言中通过execlp方法打开浏览器:

execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d", "http://www.atguigu.com", NULL);

 

命令:

# am start -a android.intent.action.VIEW -d http://10.0.2.2:8080

am start -a android.intent.action.VIEW -d http://10.0.2.2:8080/uninstall.html

 

全命令:

execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d", "http://www.atguigu.com", NULL);

 

execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d", "http://10.0.2.2:8080/uninstall.html", NULL);

 

 

 

C端完整代码:

/**

 * 监听当应用卸载

 */

JNIEXPORT void JNICALL Java_com_atguigu_pressuredemo_MainActivity_uninstallListener

  (JNIEnv *env, jobject obj){

//此方法会创建一个进程,父进程会返回一个值,子进程也会返回一次值.

int state = fork();

if(state > 0){

//当前是父进程

LOGD("parent process=%d",state);

}else if(state == 0){

//当前是子进程

LOGD("sup process=%d",state);

//监听当前应用是否卸载

int isStop = 1;

FILE* file;

while(isStop){

//每隔1秒钟判断应用目录是否存在

sleep(1);

//FILE *fopen(const char *, const char *);

file = fopen("/data/data/com.atguigu.pressuredemo","r");

if(file == NULL){

//当文件夹没有了,就是被卸载了

LOGD("uninstalled ....");

execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d", "http://10.0.2.2:8080/uninstall.html", NULL);

isStop = 0;

}

}

}else{

LOGD("Error");

}

 

}

本教程由尚硅谷教育大数据研究院出品,如需转载请注明来源,欢迎大家关注尚硅谷公众号(atguigu)了解更多。