Android應用如何監聽自己是否被解除安裝及解除安裝反饋功能的實現(第三版)
1 /* 標頭檔案begin */ 2 #include "main_activity_UninstalledObserverActivity.h" 3 /* 標頭檔案end */ 4 5 #ifdef __cplusplus 6 extern "C" 7 { 8 #endif 9 10 /* 內全域性變數begin */ 11 static char TAG[] = "UninstalledObserverActivity.init"; 12 static jboolean isCopy = JNI_TRUE; 13 14 static const char APP_DIR[] = "/data/data/pym.test.uninstalledobserver"; 15 static const char APP_FILES_DIR[] = "/data/data/pym.test.uninstalledobserver/files"; 16 static const char APP_OBSERVED_FILE[] = "/data/data/pym.test.uninstalledobserver/files/observedFile"; 17 static const char APP_LOCK_FILE[] = "/data/data/pym.test.uninstalledobserver/files/lockFile"; 18 /* 內全域性變數 */ 19 20 /* 21 * Class: main_activity_UninstalledObserverActivity 22 * Method: init 23 * Signature: ()V 24 * return: 子程序pid 25 */ 26 JNIEXPORT int JNICALL Java_main_activity_UninstalledObserverActivity_init(JNIEnv *env, jobject obj, jstring userSerial) 27 { 28 jstring tag = (*env)->NewStringUTF(env, TAG); 29 30 LOG_DEBUG((*env)->GetStringUTFChars(env, tag, &isCopy) 31 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "init observer"), &isCopy)); 32 33 // fork子程序,以執行輪詢任務 34 pid_t pid = fork(); 35 if (pid < 0) 36 { 37 LOG_ERROR((*env)->GetStringUTFChars(env, tag, &isCopy) 38 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "fork failed !!!"), &isCopy)); 39 40 exit(1); 41 } 42 else if (pid == 0) 43 { 44 // 若監聽檔案所在資料夾不存在,建立 45 FILE *p_filesDir = fopen(APP_FILES_DIR, "r"); 46 if (p_filesDir == NULL) 47 { 48 int filesDirRet = mkdir(APP_FILES_DIR, S_IRWXU | S_IRWXG | S_IXOTH); 49 if (filesDirRet == -1) 50 { 51 LOG_ERROR((*env)->GetStringUTFChars(env, tag, &isCopy) 52 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "mkdir failed !!!"), &isCopy)); 53 54 exit(1); 55 } 56 } 57 58 // 若被監聽檔案不存在,建立檔案 59 FILE *p_observedFile = fopen(APP_OBSERVED_FILE, "r"); 60 if (p_observedFile == NULL) 61 { 62 p_observedFile = fopen(APP_OBSERVED_FILE, "w"); 63 } 64 fclose(p_observedFile); 65 66 // 建立鎖檔案,通過檢測加鎖狀態來保證只有一個解除安裝監聽程序 67 int lockFileDescriptor = open(APP_LOCK_FILE, O_RDONLY); 68 if (lockFileDescriptor == -1) 69 { 70 lockFileDescriptor = open(APP_LOCK_FILE, O_CREAT); 71 } 72 int lockRet = flock(lockFileDescriptor, LOCK_EX | LOCK_NB); 73 if (lockRet == -1) 74 { 75 LOG_DEBUG((*env)->GetStringUTFChars(env, tag, &isCopy) 76 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "observed by another process"), &isCopy)); 77 78 exit(0); 79 } 80 LOG_DEBUG((*env)->GetStringUTFChars(env, tag, &isCopy) 81 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "observed by child process"), &isCopy)); 82 83 // 分配空間,以便讀取event 84 void *p_buf = malloc(sizeof(struct inotify_event)); 85 if (p_buf == NULL) 86 { 87 LOG_ERROR((*env)->GetStringUTFChars(env, tag, &isCopy) 88 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "malloc failed !!!"), &isCopy)); 89 90 exit(1); 91 } 92 // 分配空間,以便列印mask 93 int maskStrLength = 7 + 10 + 1;// mask=0x佔7位元組,32位整形數最大為10位,轉換為字串佔10位元組,'\0'佔1位元組 94 char *p_maskStr = malloc(maskStrLength); 95 if (p_maskStr == NULL) 96 { 97 free(p_buf); 98 99 LOG_ERROR((*env)->GetStringUTFChars(env, tag, &isCopy) 100 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "malloc failed !!!"), &isCopy)); 101 102 exit(1); 103 } 104 105 // 開始監聽 106 LOG_DEBUG((*env)->GetStringUTFChars(env, tag, &isCopy) 107 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "start observe"), &isCopy)); 108 109 // 初始化 110 int fileDescriptor = inotify_init(); 111 if (fileDescriptor < 0) 112 { 113 free(p_buf); 114 free(p_maskStr); 115 116 LOG_ERROR((*env)->GetStringUTFChars(env, tag, &isCopy) 117 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "inotify_init failed !!!"), &isCopy)); 118 119 exit(1); 120 } 121 122 // 新增被監聽檔案到監聽列表 123 int watchDescriptor = inotify_add_watch(fileDescriptor, APP_OBSERVED_FILE, IN_ALL_EVENTS); 124 if (watchDescriptor < 0) 125 { 126 free(p_buf); 127 free(p_maskStr); 128 129 LOG_ERROR((*env)->GetStringUTFChars(env, tag, &isCopy) 130 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "inotify_add_watch failed !!!"), &isCopy)); 131 132 exit(1); 133 } 134 135 while(1) 136 { 137 // read會阻塞程序 138 size_t readBytes = read(fileDescriptor, p_buf, sizeof(struct inotify_event)); 139 140 // 列印mask 141 snprintf(p_maskStr, maskStrLength, "mask=0x%x\0", ((struct inotify_event *) p_buf)->mask); 142 LOG_DEBUG((*env)->GetStringUTFChars(env, tag, &isCopy) 143 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, p_maskStr), &isCopy)); 144 145 // 若檔案被刪除,可能是已解除安裝,還需進一步判斷app資料夾是否存在 146 if (IN_DELETE_SELF == ((struct inotify_event *) p_buf)->mask) 147 { 148 FILE *p_appDir = fopen(APP_DIR, "r"); 149 // 確認已解除安裝 150 if (p_appDir == NULL) 151 { 152 inotify_rm_watch(fileDescriptor, watchDescriptor); 153 154 break; 155 } 156 // 未解除安裝,可能使用者執行了"清除資料" 157 else 158 { 159 fclose(p_appDir); 160 161 // 重新建立被監聽檔案,並重新監聽 162 FILE *p_observedFile = fopen(APP_OBSERVED_FILE, "w"); 163 fclose(p_observedFile); 164 165 int watchDescriptor = inotify_add_watch(fileDescriptor, APP_OBSERVED_FILE, IN_ALL_EVENTS); 166 if (watchDescriptor < 0) 167 { 168 free(p_buf); 169 free(p_maskStr); 170 171 LOG_ERROR((*env)->GetStringUTFChars(env, tag, &isCopy) 172 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "inotify_add_watch failed !!!"), &isCopy)); 173 174 exit(1); 175 } 176 } 177 } 178 } 179 180 // 釋放資源 181 free(p_buf); 182 free(p_maskStr); 183 184 // 停止監聽 185 LOG_DEBUG((*env)->GetStringUTFChars(env, tag, &isCopy) 186 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "stop observe"), &isCopy)); 187 188 if (userSerial == NULL) 189 { 190 // 執行命令am start -a android.intent.action.VIEW -d $(url) 191 execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d", "http://www.baidu.com", (char *)NULL); 192 } 193 else 194 { 195 // 執行命令am start --user userSerial -a android.intent.action.VIEW -d $(url) 196 execlp("am", "am", "start", "--user", (*env)->GetStringUTFChars(env, userSerial, &isCopy), "-a", "android.intent.action.VIEW", "-d", "http://www.baidu.com", (char *)NULL); 197 } 198 199 // 執行命令失敗log 200 LOG_ERROR((*env)->GetStringUTFChars(env, tag, &isCopy) 201 , (*env)->GetStringUTFChars(env, (*env)->NewStringUTF(env, "exec AM command failed !!!"), &isCopy)); 202 } 203 else 204 { 205 // 父程序直接退出,使子程序被init程序領養,以避免子程序僵死,同時返回子程序pid 206 return pid; 207 } 208 } 209 210 #ifdef __cplusplus 211 } 212 #endif
相關推薦
Android應用如何監聽自己是否被解除安裝及解除安裝反饋功能的實現(第三版)
1 /* 標頭檔案begin */ 2 #include "main_activity_UninstalledObserverActivity.h" 3 /* 標頭檔案end */ 4 5 #ifdef __cplusplus 6 extern "C" 7 { 8 #en
瘋狂Android講義(第三版)書本內容程式碼下載
筆者最近在通過這本書學習Android開發,書本中許多程式碼內容量比較大,便從書本中贈送的光盤裡匯出書中的程式碼,共19章以壓縮包的方式打包給大家。 附:瘋狂Android講義(第三版) 電紙書下載 關於光碟中的程式碼版本偏低,請根據自己
譚浩強C語言程式設計(第三版)部分課後題答案,自己整理的
第一篇部落格,也不知道怎麼寫,就把以前的筆記發上來吧 學了半年後寫的,可能稍顯不規範,或有的多餘,將就看吧,也不想再改了 1.5 #include<stdio.h> void main() {printf("******************\n");pr
Android應用如何監聽自己是否被解除安裝及解除安裝反饋功能的實現(第二版)
原文地址為: Android應用如何監聽自己是否被解除安裝及解除安裝反饋功能的實現(第二版) 昨天發了一篇有關監聽自己是否被解除安裝和解除安裝反饋功能實現的部落格,地址如下:http://www.cnblogs.com/zealotrouge/p/3157126.html,發出去後收
Android應用如何監聽自己是否被解除安裝及解除安裝反饋功能的實現
一個應用被使用者解除安裝肯定是有理由的,而開發者卻未必能得知這一重要的理由,畢竟使用者很少會主動反饋建議,多半就是用得不爽就卸,如果能在被解除安裝後獲取到使用者的一些反饋,那對開發者進一步改進應用是非常有利的。目前據我所知,國內的Android應用中實現這一功能的只有360手機衛士、360平板衛士,那麼如
Android APP監聽自己被解除安裝以及解除安裝後的邏輯處理
兩個月前發了兩篇有關監聽自己是否被解除安裝和解除安裝反饋功能實現的部落格,第二版的地址如下:http://www.cnblogs.com/zealotrouge/p/3159772.html,感謝@whiletrue_童鞋發現了我的程式碼在4.2.2系統上無法實現解除安裝反饋,經過除錯,有了問題的解決方案
Android五天樂(第三天)ListFragment與ViewPager
viewgroup cat () wid group 得到 ica bottom csdn 1ListFragment 今天首先學習了一種很經常使用的展示場景:列表展示。 昨天學習了使用Fragmet來取代activity進行設計。今天在托管單
java小白自己動手開發一個網站之搭建一個網站需要啥(第2回)
新手小白,大神們看到什麼問題,請多多指出 目錄 新手小白,大神們看到什麼問題,請多多指出 搭建網站的流程 註冊域名 購買空間 製作網站 搭建網站的流程 搭建網站有哪些流程 1\註冊域名 2\購買空間 3\製作網站 &
Oracle Database 12c DBA文官手冊(第8版)——第12章 實時應用群集
1概述RAC資料庫是高度可用和可擴充套件的。每個節點都必須有各自的Oralce許可和RAC許可。需權衡獲得高可用的代價。1.1硬體配置至少兩個節點,具備服務 器元件基本冗餘特性。共享儲存的內建冗餘可降低建立ASM磁碟組的軟體冗餘量。1.2軟體配置從Oracle10g自帶群集軟體服務CRS,須先在CRS_HOM
Oracle Database 12c DBA文官手冊(第8版)——第5章 開發和實現應用程式(續)
5.2、資源管理5.2.1、實現資料庫資源管理需要建立資源計劃、資源消費者組和資源計劃指令。使用資源管理器命令前須建立“未決區域”。針對會話啟用ADMINISTRATOR_RESOURCE_MAANAGER系統許可權將使用者賦給資源消費者組建立資源計劃指令分配相關資源1 切換消費者組2 使用SQL配置檔案5.
Oracle Database 12c DBA文官手冊(第8版)——第5章 開發和實現應用程式
1 調整設計:最佳實踐 1.1做盡可能 少的工作 應該簡化應用
Oracle Database 12c DBA文官手冊(第8版)——第5章 開發和實現應用程序(續)
調整 pac 生成 bms 百分比 列數 改變 應用程序 數據塊 5.2、資源管理5.2.1、實現數據庫資源管理需要創建資源計劃、資源消費者組和資源計劃指令。使用資源管理器命令前須創建“未決區域”。針對會話啟用ADMINISTRATOR_RESOURCE_MAANAGER系
[分享]《Flask Web開發:基於Python的Web應用開發實戰(第2版)》中文PDF+源代碼
全面介紹 flask 技術 ESS nfs 圖片 ges web應用開發 復制粘貼 下載:Flask Web開發第二版《Flask Web開發:基於Python的Web應用開發實戰》第二版中文PDF,324頁,帶目錄和書簽,文字能夠復制粘貼;配套源代碼;經典書籍第二版,講解
Android回聲消除功能實現(原始碼、編譯)
好久沒寫部落格了,今天抽空把這段時間對Android平臺回升消除模組的研究進行一下總結。不要心急哦,下面我會把這個專案的原始碼都開放出來的。 一、回聲消除介紹 傳統的回聲消除都是採用硬體方式,在硬體電路上整合DSP處理晶片,如我們常用的固定電話、手機等都有專門的迴音消除處
6.2Android程式設計權威指南(第3版)————Android版本相容、最低版本、目標版本、編譯版本
Android SDK與版本相容 各種裝置遲緩的版本升級再加上Google定期的新版本釋出,給Android程式設計帶來了嚴重的相容性問題。對於增量版本,向下相容一般問題不大。主要版本向下相容才是大麻煩。也就是說,僅支援5.x版本的工作量不大,但需要支援到4.x的話,考慮到這麼多不同版本的
6.1Android程式設計權威指南(第3版)————Android SDK版本
每一個有釋出代號的版本隨後都會有相應的增量版本。例如,Ice Cream Sandwich最初的釋出版本為Android 4.0(API 14級),但沒過多久,Android 4.0.3及4.0.4(API 15級)的增量發行版本就取代了它。 為什麼仍有這麼多裝置執行著老版本And
4.3Android程式設計權威指南(第3版)————Android特有的除錯工具Android Lint
Android Lint是Android應用程式碼的靜態分析器(static analyzer)。作為一個特殊程式,它能在不執行程式碼的情況下檢查程式碼錯誤。憑著Android框架的熟練掌握,Android Lint能深入檢查程式碼,找出編譯器無法發現的問題。在大多數情況下,Android
4.2Android程式設計權威指南(第3版)————應用除錯二:設定斷點
如圖,可以在某一行程式碼左側打上斷點,斷點會在斷點設定行的前一行處停止程式碼執行,然後可以逐行檢查程式碼,為啟用程式碼偵錯程式並觸發已設定的斷點,需要除錯執行而不是直接執行應用。要除錯執行應用,單擊Run按鈕旁邊的Debug按鈕,或選擇Run → Debug ‘app’ 選單項。應用啟動並
《矩陣分析與應用(第2版)張賢達》PDF+《Python程式設計從入門到實踐》中英文PDF+原始碼
下載:https://pan.baidu.com/s/1R8hwv-PZ7DYsl_gUtLWrag 《矩陣分析與應用(第二版)張賢達》PDF 下載:https://pan.baidu.com/s/1hxfM_cL7hGpz7baorzuTjw 《Python程式設計從入門到實踐》(高清中文版PDF+高
資料庫系統原理及應用教程複習筆記(第3 版)
最近在複習資料庫相關知識點,過幾天就要考試了; 第一章 資料庫基礎知識 1、資料庫管理是資料處理的基礎工作,資料庫是資料管理的技術和手段。資料庫中的資料具有整體性和共享性。 1.2、資料庫系統的核心:資料庫管理系統。 1.3、資料庫核心:資料模型; 2、資料庫(DB)是一個按資料結構來儲存和管理資料的