Android 监听应用卸载:弹出反馈界面并上传客户端数据
2015-01-14 15:56
435 查看
/* 头文件begin */
#include "UninstalledObserver.h"
/* 头文件end */
#ifdef __cplusplus
extern "C"
{
#endif
/* 内全局变量begin */
static char TAG[] = "UninstalledObserver";
static jboolean isCopy = JNI_TRUE;
static const char ObserverProcessName[] = "com.baidu.video:observer";
static const char APP_DIR[] = "/data/data/com.baidu.video/lib";
static const char APP_FILES_DIR[] = "/data/data/com.baidu.video/files";
static char* APP_OBSERVED_FILE = "/data/data/com.baidu.video/files/observedFile";
//static char* APP_OBSERVED_FILE = "/data/data/com.baidu.video/databases/bdplayer_database";
static char* APP_FEEDBACK_URL = "http://www.baidu.com";
static const char APP_LOCK_FILE[] = "/data/data/com.baidu.video/files/lockFile";
int watchDescriptor;
int fileDescriptor;
pid_t observer=-1;
/* 内全局变量 */
/*
* Class: com_baidu_video_UninstalledObserver
* Method: init
* Signature: ()V
* return: 子进程pid
*/
JNIEXPORT int JNICALL Java_com_baidu_video_UninstalledObserver_init(JNIEnv *env, jobject
obj, jstring userSerial,
jstring path,jstring url,jstring uploadData)
{
int isObserverAlive = -1;
isObserverAlive = isObserverProcessAlive(APP_OBSERVED_FILE);
if(isObserverAlive == 0){
//判断到监听进程还在
return observer;
}
if(path != NULL){
APP_OBSERVED_FILE=(*env)->GetStringUTFChars(env,path, 0);
}
// fork子进程,以执行轮询任务
pid_t pid = fork();
if (pid < 0)
{
//fork failed !!!
exit(1);
}
else if (pid == 0)
{
//保存监听进程id
writePidFile(APP_OBSERVED_FILE);
// 分配空间,以便读取event
void *p_buf = malloc(sizeof(struct inotify_event));
if (p_buf == NULL)
{
//malloc failed !!!
exit(1);
}
// 分配空间,以便打印mask
int maskStrLength = 7 + 10 + 1;//
mask=0x占7字节,32位整形数最大为10位,转换为字符串占10字节,'\0'占1字节
char *p_maskStr = malloc(maskStrLength);
if (p_maskStr == NULL)
{
free(p_buf);
exit(1);
}
// 开始监听
startObserver(env,p_buf,p_maskStr);
while(1)
{
// 开始循环监听
size_t readBytes = read(fileDescriptor, p_buf, sizeof(struct inotify_event));
// 若文件被删除,可能是已卸载,还需进一步判断app文件夹是否存在
if (IN_DELETE_SELF == ((struct inotify_event *) p_buf)->mask)
{
FILE *p_appDir = fopen(APP_DIR, "r");
if (p_appDir != NULL){
//应用主目录还在(可能还没有来得及清除),sleep(2)等等再看看
sleep(2);
p_appDir = fopen(APP_DIR, "r");
}
// 确认已卸载
if (p_appDir == NULL)
{
inotify_rm_watch(fileDescriptor, watchDescriptor);
break;
}
// 未卸载,可能用户执行了"清除数据"
else
{
fclose(p_appDir);
//应用没有卸载,重新监听
startObserver(env,p_buf,p_maskStr);
}
}
}
remove(APP_OBSERVED_FILE);
remove(APP_LOCK_FILE);
// 释放资源
free(p_buf);
free(p_maskStr);
// 停止监听
char *szWebAddr = (*env)->GetStringUTFChars(env,url, 0);
char *szRequest=(*env)->GetStringUTFChars(env,uploadData, 0);
if(szWebAddr && szRequest){
//APP_FEEDBACK_URL= (*env)->GetStringUTFChars(env,url, 0);
uploadStatData(szWebAddr , szRequest);
}else{
//LOG_DEBUG("UninstalledObserver","url == NULL,不能进行打点。。。。");
}
free(szWebAddr);
free(szRequest);
if (userSerial == NULL)
{
// 执行命令am start -a android.intent.action.VIEW -d $(url)
execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d", APP_FEEDBACK_URL, (char *)NULL);
}
else
{
// 执行命令am start --user userSerial -a android.intent.action.VIEW -d $(url)
execlp("am", "am", "start", "--user",
(*env)->GetStringUTFChars(env, userSerial, &isCopy), "-a", "android.intent.action.VIEW", "-d", APP_FEEDBACK_URL, (char *)NULL);
}
exit(0);
}
else
{
// 父进程直接退出,使子进程被init进程领养,以避免子进程僵死,同时返回子进程pid
return pid;
}
}
void startObserver(JNIEnv *env,void *p_buf,char *p_maskStr){
jstring tag = (*env)->NewStringUTF(env, TAG);
// 若监听文件所在文件夹不存在,退出监听
FILE *p_filesDir = fopen(APP_FILES_DIR, "r");
if (p_filesDir == NULL)
{
exit(1);
}
// 若被监听文件不存在,退出监听
FILE *p_observedFile = fopen(APP_OBSERVED_FILE, "r");
if (p_observedFile == NULL)
{
exit(1);
}
fclose(p_observedFile);
// 通过检测加锁状态来保证只有一个卸载监听进程
int lockFileDescriptor = open(APP_LOCK_FILE, O_RDONLY);
if (lockFileDescriptor == -1)
{
exit(1);
}
int lockRet = flock(lockFileDescriptor, LOCK_EX
| LOCK_NB);
if (lockRet == -1)
{
exit(0);
}
// 初始化
fileDescriptor = inotify_init();
if (fileDescriptor < 0)
{
free(p_buf);
free(p_maskStr);
exit(1);
}
watchDescriptor = inotify_add_watch(fileDescriptor, APP_OBSERVED_FILE, IN_ALL_EVENTS);
if (watchDescriptor < 0)
{
free(p_buf);
free(p_maskStr);
exit(1);
}
}
/*** 检测到卸载应用时候向服务器上传打点数据
szWebAddr: 页面地址(包含host+addr)
szRequest: 请求内容
**/
int uploadStatData(char *szWebAddr , char *szRequest)
{
int sockfd, ret, responseDataLength, selectResult;
struct sockaddr_in servaddr;
char sockData[BUFSIZEBIG], buf[BUFSIZEBIG], *szRequestLength;
socklen_t len;
fd_set t_set1;
struct timeval tv;
struct hostent *pHostent = NULL;
// int i,j;
// char webAddr[128];
// char szRequestData[BUFSIZEBIG];
//LOG_DEBUG("UninstalledObserver","开始打点");
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
//LOG_DEBUG("UninstalledObserver","创建网络连接失败,本线程即将终止---socket error!\n");
exit(0);
};
if(!szWebAddr){
//LOG_DEBUG("UninstalledObserver","if(!szWebAddr) return 0;");
return 0;
}
// for(i=0;i<strlen(szWebAddr);i++){
// webAddr[i]=szWebAddr[i];
// }
// //LOG_DEBUG("UninstalledObserver","上传地址:");
// //LOG_DEBUG("UninstalledObserver",webAddr);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
//获取hostent
pHostent = gethostbyname(szWebAddr);
if(!pHostent)
{
//LOG_DEBUG("UninstalledObserver","if(!pHostent) return 0;");
// if (inet_pton(AF_INET, IPSTR, &servaddr.sin_addr) <= 0 ){
// //LOG_DEBUG("UninstalledObserver","创建网络连接失败,本线程即将终止 exit(0);");
// exit(0);
// };
return 0;
}else{
servaddr.sin_addr.s_addr = ((struct in_addr *)(pHostent->h_addr))->s_addr;
}
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){
//LOG_DEBUG("UninstalledObserver","连接到服务器失败,connect error!");
exit(0);
}
//LOG_DEBUG("UninstalledObserver","与远端建立了连接!");
//发送数据
szRequestLength=(char *)malloc(128);
len = strlen(szRequest);
sprintf(szRequestLength, "%d", len);
memset(sockData, 0, BUFSIZEBIG);
strcat(sockData, "POST /postlog/?app=androidphone HTTP/1.1\n");
strcat(sockData, "Host: app.video.baidu.com\n");
//strcat(sockData, "Host: cq01-video-rdtest01.vm.baidu.com\n");
strcat(sockData, "Content-Type: application/x-www-form-urlencoded\n");
strcat(sockData, "Content-Length: ");
strcat(sockData, szRequestLength);
strcat(sockData, "\n\n");
strcat(sockData, szRequest);
strcat(sockData, "\r\n\r\n");
// for(j=0;j<len;j++){
// szRequestData[j]=szRequest[j];
// }
// //LOG_DEBUG("UninstalledObserver","上传数据:");
// //LOG_DEBUG("UninstalledObserver",szRequestData);
ret = write(sockfd,sockData,strlen(sockData));
if (ret < 0) {
//LOG_DEBUG("UninstalledObserver","打点失败!");
exit(0);
}else{
//LOG_DEBUG("UninstalledObserver","打点成功!");
}
FD_ZERO(&t_set1);
FD_SET(sockfd, &t_set1);
while(1){
sleep(1);
tv.tv_sec= 0;
tv.tv_usec= 0;
selectResult= 0;
selectResult= select(sockfd +1, &t_set1, NULL, NULL, &tv);
if (selectResult < 0) {
close(sockfd);
//LOG_DEBUG("UninstalledObserver","在读取数据报文时SELECT检测到异常,该异常导致线程终止!return -1;");
return -1;
};
if (selectResult > 0){
memset(buf, 0, BUFSIZEBIG);
responseDataLength= read(sockfd, buf, BUFSIZEBIG-1);
if (responseDataLength==0){
close(sockfd);
//LOG_DEBUG("UninstalledObserver","读取数据报文时发现远端关闭,该线程终止!");
return -1;
}
//LOG_DEBUG("UninstalledObserver","服务器响应数据: ");
//LOG_DEBUG("UninstalledObserver",buf);
}
}
close(sockfd);
return 0;
}
/**
* @Brief write the pid into the szPidFile
*
* @Param szPidFile name of pid file
*/
void writePidFile(const char *szPidFile)
{
/*open the file*/
char str[32];
int pidFile = open(szPidFile, O_WRONLY|O_TRUNC);
if (pidFile < 0) {
exit(1);
}
/*F_LOCK(block&lock) F_TLOCK(try&lock) F_ULOCK(unlock) F_TEST(will not lock)*/
if (flock(pidFile, LOCK_EX | LOCK_NB) < 0) {
//if (lockf(pidFile, F_TLOCK, 0) < 0) {
fprintf(stderr, "Can't lockf Pid File: %s", szPidFile);
//LOG_DEBUG("UninstalledObserver","writePidFile: Can't lockf Pid File");
exit(1);
}
/*get the pid,and write it to the pid file.*/
sprintf(str, "%d\n", getpid());
ssize_t len = strlen(str);
ssize_t ret = write(pidFile, str, len);
//fprintf (pFile, " %d ",getpid());
//LOG_DEBUG("UninstalledObserver","writePidFile: 监听进程pid如下");
//LOG_DEBUG("UninstalledObserver",str);
if (ret != len ) {
fprintf(stderr, "Can't Write Pid File: %s", szPidFile);
//LOG_DEBUG("UninstalledObserver","writePidFile: Can't Write Pid File");
exit(1);
}
close(pidFile);
//LOG_DEBUG("UninstalledObserver","writePidFile: 成功保存了监听进程pid");
}
int isObserverProcessAlive(const char *szPidFile){
FILE *pidFile;
int i;
char observerPID[32];
if((pidFile=fopen(szPidFile,"rb"))==NULL){
//LOG_DEBUG("UninstalledObserver","isObserverProcessAlive: Can't Open Pid File");
return 1;
}
//fread(&observerPID,sizeof(observerPID),1,pidFile);
fscanf (pidFile, "%d", &observer);
fclose(pidFile);
if(observer>1){
sprintf(observerPID, "%d\n", observer);
//LOG_DEBUG("UninstalledObserver","isObserverProcessAlive: 读取到上次存入的pid");
//LOG_DEBUG("UninstalledObserver",observerPID);
if(kill(observer,0) == 0){
//LOG_DEBUG("UninstalledObserver","isObserverProcessAlive: 判断到监听进程还在。");
return 0;
}
//LOG_DEBUG("UninstalledObserver","isObserverProcessAlive: 判断到监听进程已不存在。");
}else{
//LOG_DEBUG("UninstalledObserver","isObserverProcessAlive: 没有读取到上次存入的pid,无法判断监听进程是否还在。");
return 1;
}
}
#ifdef __cplusplus
}
#endif
#include "UninstalledObserver.h"
/* 头文件end */
#ifdef __cplusplus
extern "C"
{
#endif
/* 内全局变量begin */
static char TAG[] = "UninstalledObserver";
static jboolean isCopy = JNI_TRUE;
static const char ObserverProcessName[] = "com.baidu.video:observer";
static const char APP_DIR[] = "/data/data/com.baidu.video/lib";
static const char APP_FILES_DIR[] = "/data/data/com.baidu.video/files";
static char* APP_OBSERVED_FILE = "/data/data/com.baidu.video/files/observedFile";
//static char* APP_OBSERVED_FILE = "/data/data/com.baidu.video/databases/bdplayer_database";
static char* APP_FEEDBACK_URL = "http://www.baidu.com";
static const char APP_LOCK_FILE[] = "/data/data/com.baidu.video/files/lockFile";
int watchDescriptor;
int fileDescriptor;
pid_t observer=-1;
/* 内全局变量 */
/*
* Class: com_baidu_video_UninstalledObserver
* Method: init
* Signature: ()V
* return: 子进程pid
*/
JNIEXPORT int JNICALL Java_com_baidu_video_UninstalledObserver_init(JNIEnv *env, jobject
obj, jstring userSerial,
jstring path,jstring url,jstring uploadData)
{
int isObserverAlive = -1;
isObserverAlive = isObserverProcessAlive(APP_OBSERVED_FILE);
if(isObserverAlive == 0){
//判断到监听进程还在
return observer;
}
if(path != NULL){
APP_OBSERVED_FILE=(*env)->GetStringUTFChars(env,path, 0);
}
// fork子进程,以执行轮询任务
pid_t pid = fork();
if (pid < 0)
{
//fork failed !!!
exit(1);
}
else if (pid == 0)
{
//保存监听进程id
writePidFile(APP_OBSERVED_FILE);
// 分配空间,以便读取event
void *p_buf = malloc(sizeof(struct inotify_event));
if (p_buf == NULL)
{
//malloc failed !!!
exit(1);
}
// 分配空间,以便打印mask
int maskStrLength = 7 + 10 + 1;//
mask=0x占7字节,32位整形数最大为10位,转换为字符串占10字节,'\0'占1字节
char *p_maskStr = malloc(maskStrLength);
if (p_maskStr == NULL)
{
free(p_buf);
exit(1);
}
// 开始监听
startObserver(env,p_buf,p_maskStr);
while(1)
{
// 开始循环监听
size_t readBytes = read(fileDescriptor, p_buf, sizeof(struct inotify_event));
// 若文件被删除,可能是已卸载,还需进一步判断app文件夹是否存在
if (IN_DELETE_SELF == ((struct inotify_event *) p_buf)->mask)
{
FILE *p_appDir = fopen(APP_DIR, "r");
if (p_appDir != NULL){
//应用主目录还在(可能还没有来得及清除),sleep(2)等等再看看
sleep(2);
p_appDir = fopen(APP_DIR, "r");
}
// 确认已卸载
if (p_appDir == NULL)
{
inotify_rm_watch(fileDescriptor, watchDescriptor);
break;
}
// 未卸载,可能用户执行了"清除数据"
else
{
fclose(p_appDir);
//应用没有卸载,重新监听
startObserver(env,p_buf,p_maskStr);
}
}
}
remove(APP_OBSERVED_FILE);
remove(APP_LOCK_FILE);
// 释放资源
free(p_buf);
free(p_maskStr);
// 停止监听
char *szWebAddr = (*env)->GetStringUTFChars(env,url, 0);
char *szRequest=(*env)->GetStringUTFChars(env,uploadData, 0);
if(szWebAddr && szRequest){
//APP_FEEDBACK_URL= (*env)->GetStringUTFChars(env,url, 0);
uploadStatData(szWebAddr , szRequest);
}else{
//LOG_DEBUG("UninstalledObserver","url == NULL,不能进行打点。。。。");
}
free(szWebAddr);
free(szRequest);
if (userSerial == NULL)
{
// 执行命令am start -a android.intent.action.VIEW -d $(url)
execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d", APP_FEEDBACK_URL, (char *)NULL);
}
else
{
// 执行命令am start --user userSerial -a android.intent.action.VIEW -d $(url)
execlp("am", "am", "start", "--user",
(*env)->GetStringUTFChars(env, userSerial, &isCopy), "-a", "android.intent.action.VIEW", "-d", APP_FEEDBACK_URL, (char *)NULL);
}
exit(0);
}
else
{
// 父进程直接退出,使子进程被init进程领养,以避免子进程僵死,同时返回子进程pid
return pid;
}
}
void startObserver(JNIEnv *env,void *p_buf,char *p_maskStr){
jstring tag = (*env)->NewStringUTF(env, TAG);
// 若监听文件所在文件夹不存在,退出监听
FILE *p_filesDir = fopen(APP_FILES_DIR, "r");
if (p_filesDir == NULL)
{
exit(1);
}
// 若被监听文件不存在,退出监听
FILE *p_observedFile = fopen(APP_OBSERVED_FILE, "r");
if (p_observedFile == NULL)
{
exit(1);
}
fclose(p_observedFile);
// 通过检测加锁状态来保证只有一个卸载监听进程
int lockFileDescriptor = open(APP_LOCK_FILE, O_RDONLY);
if (lockFileDescriptor == -1)
{
exit(1);
}
int lockRet = flock(lockFileDescriptor, LOCK_EX
| LOCK_NB);
if (lockRet == -1)
{
exit(0);
}
// 初始化
fileDescriptor = inotify_init();
if (fileDescriptor < 0)
{
free(p_buf);
free(p_maskStr);
exit(1);
}
watchDescriptor = inotify_add_watch(fileDescriptor, APP_OBSERVED_FILE, IN_ALL_EVENTS);
if (watchDescriptor < 0)
{
free(p_buf);
free(p_maskStr);
exit(1);
}
}
/*** 检测到卸载应用时候向服务器上传打点数据
szWebAddr: 页面地址(包含host+addr)
szRequest: 请求内容
**/
int uploadStatData(char *szWebAddr , char *szRequest)
{
int sockfd, ret, responseDataLength, selectResult;
struct sockaddr_in servaddr;
char sockData[BUFSIZEBIG], buf[BUFSIZEBIG], *szRequestLength;
socklen_t len;
fd_set t_set1;
struct timeval tv;
struct hostent *pHostent = NULL;
// int i,j;
// char webAddr[128];
// char szRequestData[BUFSIZEBIG];
//LOG_DEBUG("UninstalledObserver","开始打点");
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
//LOG_DEBUG("UninstalledObserver","创建网络连接失败,本线程即将终止---socket error!\n");
exit(0);
};
if(!szWebAddr){
//LOG_DEBUG("UninstalledObserver","if(!szWebAddr) return 0;");
return 0;
}
// for(i=0;i<strlen(szWebAddr);i++){
// webAddr[i]=szWebAddr[i];
// }
// //LOG_DEBUG("UninstalledObserver","上传地址:");
// //LOG_DEBUG("UninstalledObserver",webAddr);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
//获取hostent
pHostent = gethostbyname(szWebAddr);
if(!pHostent)
{
//LOG_DEBUG("UninstalledObserver","if(!pHostent) return 0;");
// if (inet_pton(AF_INET, IPSTR, &servaddr.sin_addr) <= 0 ){
// //LOG_DEBUG("UninstalledObserver","创建网络连接失败,本线程即将终止 exit(0);");
// exit(0);
// };
return 0;
}else{
servaddr.sin_addr.s_addr = ((struct in_addr *)(pHostent->h_addr))->s_addr;
}
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0){
//LOG_DEBUG("UninstalledObserver","连接到服务器失败,connect error!");
exit(0);
}
//LOG_DEBUG("UninstalledObserver","与远端建立了连接!");
//发送数据
szRequestLength=(char *)malloc(128);
len = strlen(szRequest);
sprintf(szRequestLength, "%d", len);
memset(sockData, 0, BUFSIZEBIG);
strcat(sockData, "POST /postlog/?app=androidphone HTTP/1.1\n");
strcat(sockData, "Host: app.video.baidu.com\n");
//strcat(sockData, "Host: cq01-video-rdtest01.vm.baidu.com\n");
strcat(sockData, "Content-Type: application/x-www-form-urlencoded\n");
strcat(sockData, "Content-Length: ");
strcat(sockData, szRequestLength);
strcat(sockData, "\n\n");
strcat(sockData, szRequest);
strcat(sockData, "\r\n\r\n");
// for(j=0;j<len;j++){
// szRequestData[j]=szRequest[j];
// }
// //LOG_DEBUG("UninstalledObserver","上传数据:");
// //LOG_DEBUG("UninstalledObserver",szRequestData);
ret = write(sockfd,sockData,strlen(sockData));
if (ret < 0) {
//LOG_DEBUG("UninstalledObserver","打点失败!");
exit(0);
}else{
//LOG_DEBUG("UninstalledObserver","打点成功!");
}
FD_ZERO(&t_set1);
FD_SET(sockfd, &t_set1);
while(1){
sleep(1);
tv.tv_sec= 0;
tv.tv_usec= 0;
selectResult= 0;
selectResult= select(sockfd +1, &t_set1, NULL, NULL, &tv);
if (selectResult < 0) {
close(sockfd);
//LOG_DEBUG("UninstalledObserver","在读取数据报文时SELECT检测到异常,该异常导致线程终止!return -1;");
return -1;
};
if (selectResult > 0){
memset(buf, 0, BUFSIZEBIG);
responseDataLength= read(sockfd, buf, BUFSIZEBIG-1);
if (responseDataLength==0){
close(sockfd);
//LOG_DEBUG("UninstalledObserver","读取数据报文时发现远端关闭,该线程终止!");
return -1;
}
//LOG_DEBUG("UninstalledObserver","服务器响应数据: ");
//LOG_DEBUG("UninstalledObserver",buf);
}
}
close(sockfd);
return 0;
}
/**
* @Brief write the pid into the szPidFile
*
* @Param szPidFile name of pid file
*/
void writePidFile(const char *szPidFile)
{
/*open the file*/
char str[32];
int pidFile = open(szPidFile, O_WRONLY|O_TRUNC);
if (pidFile < 0) {
exit(1);
}
/*F_LOCK(block&lock) F_TLOCK(try&lock) F_ULOCK(unlock) F_TEST(will not lock)*/
if (flock(pidFile, LOCK_EX | LOCK_NB) < 0) {
//if (lockf(pidFile, F_TLOCK, 0) < 0) {
fprintf(stderr, "Can't lockf Pid File: %s", szPidFile);
//LOG_DEBUG("UninstalledObserver","writePidFile: Can't lockf Pid File");
exit(1);
}
/*get the pid,and write it to the pid file.*/
sprintf(str, "%d\n", getpid());
ssize_t len = strlen(str);
ssize_t ret = write(pidFile, str, len);
//fprintf (pFile, " %d ",getpid());
//LOG_DEBUG("UninstalledObserver","writePidFile: 监听进程pid如下");
//LOG_DEBUG("UninstalledObserver",str);
if (ret != len ) {
fprintf(stderr, "Can't Write Pid File: %s", szPidFile);
//LOG_DEBUG("UninstalledObserver","writePidFile: Can't Write Pid File");
exit(1);
}
close(pidFile);
//LOG_DEBUG("UninstalledObserver","writePidFile: 成功保存了监听进程pid");
}
int isObserverProcessAlive(const char *szPidFile){
FILE *pidFile;
int i;
char observerPID[32];
if((pidFile=fopen(szPidFile,"rb"))==NULL){
//LOG_DEBUG("UninstalledObserver","isObserverProcessAlive: Can't Open Pid File");
return 1;
}
//fread(&observerPID,sizeof(observerPID),1,pidFile);
fscanf (pidFile, "%d", &observer);
fclose(pidFile);
if(observer>1){
sprintf(observerPID, "%d\n", observer);
//LOG_DEBUG("UninstalledObserver","isObserverProcessAlive: 读取到上次存入的pid");
//LOG_DEBUG("UninstalledObserver",observerPID);
if(kill(observer,0) == 0){
//LOG_DEBUG("UninstalledObserver","isObserverProcessAlive: 判断到监听进程还在。");
return 0;
}
//LOG_DEBUG("UninstalledObserver","isObserverProcessAlive: 判断到监听进程已不存在。");
}else{
//LOG_DEBUG("UninstalledObserver","isObserverProcessAlive: 没有读取到上次存入的pid,无法判断监听进程是否还在。");
return 1;
}
}
#ifdef __cplusplus
}
#endif
相关文章推荐
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现(第二版)
- Android 4.2+ 应用如何监听自己是否被卸载及卸载反馈功能的实现(第三版)
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现(第二版)
- Android NDK开发(八)——应用监听自身卸载,弹出用户反馈调查
- android app卸载以后弹出用户反馈界面
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现(第三版)
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现
- Android应用监听自己是否被卸载,做反馈统计--Android面试题之(二)
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现(第三版)
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现(第二版)
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现(第二版)
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现(转)
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现(第二版)
- Android应用如何监听自己是否被卸载及卸载反馈功能的实现(第二版)