您的位置:首页 > 移动开发 > Android开发

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐