Lsn19_AM命令源碼分析

NDK開發彙總

一 360手機助手之卸載監聽

Android系統下列監聽方式

  1. 監聽系統卸載廣播:只能監聽到其他應用的卸載廣播,無法監聽到自己是否被卸載。

ACTION_PACKAGE_REMOVED
ACTION_PACKAGE_REMOVED
皮之不存毛將焉附
內存 --》
監聽 別人

  1. 卸載 系統log (正在被安裝的包程序不能接收到這個廣播), 監聽自身

  2. Java線程 輪訓 監聽 監聽/data/data/{package-name}目錄是否存在

  3. C進程 監聽/data/data/{package-name}目錄是否存在 跳轉到網頁

上述4種方式均不能監聽自身的卸載,可以用下面的方式實現

  1. 靜默安裝另外的apk 監聽自己是否被卸載 可以 (root)
監聽  /data/data/{package-name}目錄是否存在

從前四種方案可以看到,單純的Java層代碼是無法監聽自身卸載的。既然Java層無法實現,我們試着使用C語言在底層實現。

實現方式

藉助Linux進程fork出來的C進程在應用被卸載後不會被銷燬,監聽/data/data/{package-name}目錄是否存在,如果不存在,就證明應用被卸載了。

  1. fork()子進程
  2. 創建監聽文件
  3. 初始化inotify實例
  4. 註冊監聽事件
  5. 調用read函數開始監聽
  6. 卸載反饋統計

加載

init native
android-6.0.0_r1\frameworks\base\core\jni
//初始化監聽
private native int init();
private native int startWatching(int fd, String path, int mask);

fork(); 開兩個進程
一個函數 1

  一個進程調用fork()函數後,系統先給新的進程分配資源,例如存儲數據和代碼的空間。
  然後把原來的進程的所有值都複製到新的新進程中,只有少數值與原來的進程的值不同。相當於克隆了一個自己。

它是一個內核用於通知用戶空間程序文件系統變化的機制。

結構中的 wd 爲被監視目標的 watch 描述符,
mask 爲事件類型
len 爲 name字符串的長度
name 爲被監視目標的路徑名,該結構的 name 字段爲一個樁
它只是爲了用戶方面引用文件名,文件名是變長的,

buf 是一個 inotify_event 結構的數組指針,
BUF_LEN 指定要讀取的總長度,
buf 大小至少要不小於 BUF_LEN,
該調用返回的事件數取決於 BUF_LEN 以及事件中文件名的長度
。Len 爲實際讀去的字節數,即獲得的事件的總長度。

IN_ACCESS,即文件被訪問
IN_MODIFY,文件被 write
IN_ATTRIB,文件屬性被修改,如 chmod、chown、touch 等
IN_CLOSE_WRITE,可寫文件被 close
IN_CLOSE_NOWRITE,不可寫文件被 close
IN_OPEN,文件被 open
IN_MOVED_FROM,文件被移走,如 mv
IN_MOVED_TO,文件被移來,如 mv、cp
IN_CREATE,創建新文件
IN_DELETE,文件被刪除,如 rm
IN_DELETE_SELF,自刪除,即一個可執行文件在執行時刪除自己
IN_MOVE_SELF,自移動,即一個可執行文件在執行時移動自己
IN_UNMOUNT,宿主文件系統被 umount
IN_CLOSE,文件被關閉,等同於(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
IN_MOVE,文件被移動,等同於(IN_MOVED_FROM | IN_MOVED_TO)

注:上面所說的文件也包括目錄。

作業
#include <stdio.h>
int main(int argc, char* argv[]) {
fork();
fork() && fork() || fork();
fork();

} 求 進程 數量

Intent

  am start -n com.yuanhh.app/.MainActivity

am 不需要彈選擇框

主要代碼

#include <jni.h>
#include <string>
#include <sys/inotify.h>
#include <fcntl.h>
#include <android/log.h>
#include <malloc.h>
#include <unistd.h>
#define LOG_TAG "tuch"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
extern "C"
{




JNIEXPORT void JNICALL
Java_com_dongnao_ls19uninstall_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject obg,jint sdk,jstring path) {
//    pid_t pid=fork();
//    if (pid < 0) {
//        LOGD("fork失敗");
////        系統fork()
//    } else if (pid > 0) {
//        LOGD("父進程");
//    } else{
//        LOGD("子進程");
//        //    初始化  inotify
//
//        int observer = open(observerFile, O_RDONLY);
//        if (observer == -1) {
//            //不存在就創建
//            observer = open(observerFile, O_CREAT);
//        }
//        int fileDescriple = inotify_init();
//        int watch=inotify_add_watch(fileDescriple, observerFile, IN_DELETE_SELF);
//        if (watch < 0) {
//            LOGD("監聽失敗");
//        }
//        void *p_buf=malloc(sizeof(struct inotify_event));
//        //        阻塞式函數  anr
//        size_t readBytes=read(fileDescriple,p_buf, sizeof(struct inotify_event));
//// 主進程   1
////        執行到下面來了    文件發生了改變  用戶卸載了 app
//        LOGD("監聽類型 %d    ,%d",((struct inotify_event *) p_buf)->mask,IN_DELETE_SELF);
//        if (((struct inotify_event *) p_buf)->mask == IN_DELETE_SELF) {
//////                覆蓋安裝
////                FILE *app_file = fopen("/data/data/com.dongnao.ls19uninstall", "r");
////            if (app_file == NULL) {
////                //   刪除app   移除監聽
////                inotify_rm_watch(fileDescriple, watch);
////            } else{
////                //   覆蓋安裝    重新進行監聽
////                fclose(app_file);
////                FILE *p_observelFile = fopen(observerFile, "w");
////                int watchDescip=inotify_add_watch(fileDescriple, observerFile, IN_DELETE_SELF);
////            }
//            }
//        LOGD("跳轉網頁");
////        鐵了心要刪除app  sdk   17   am  設置到環境變量   多用戶的操作
//            if (sdk < 17) {
//                execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d",
//                       "http://www.baidu.com",NULL);
//
//            } else{
//                execlp("am", "am", "start","--user","0","-a", "android.intent.action.VIEW", "-d",
//                       "http://www.baidu.com",NULL);
//            }
//
//    }

}

JNIEXPORT void JNICALL
Java_com_dongnao_ls19uninstall_MainActivity_load__ILjava_lang_String_2(JNIEnv *env,
                                                                       jobject instance, jint sdk,
                                                                       jstring path_) {
    const char *path = env->GetStringUTFChars(path_, 0);
    pid_t pid=fork();
    if (pid < 0) {
        LOGD("fork失敗");
//        系統fork()
    } else if (pid > 0) {
        LOGD("父進程");
    } else {
        LOGD("子進程");
        //    初始化  inotify
        int fileDescriple = inotify_init();
        int watch=inotify_add_watch(fileDescriple, path, IN_DELETE_SELF);
        void *p_buf=malloc(sizeof(struct inotify_event));
        //        阻塞式函數  anr
        size_t readBytes=read(fileDescriple,p_buf, sizeof(struct inotify_event));
        inotify_rm_watch(fileDescriple, watch);
        LOGD("跳轉網頁");
//        鐵了心要刪除app  sdk   17   am  設置到環境變量   多用戶的操作
        if (sdk < 17) {
            execlp("am", "am", "start", "-a", "android.intent.action.VIEW", "-d",
                   "http://www.baidu.com",NULL);

        } else{
            execlp("am", "am", "start","--user","0","-a", "android.intent.action.VIEW", "-d",
                   "http://www.baidu.com",NULL);
        }
    }

    // TODO

    env->ReleaseStringUTFChars(path_, path);
}


}

二 AM

● -a : 指定Intent action, 實現原理Intent.setAction();
● -n : 指定組件名,格式爲{包名}/.{主Activity名},實現原理Intent.setComponent();
● -d <DATA_URI>: 指定Intent data URI
● -t <MIME_TYPE>: 指定Intent MIME Type
● -c [-c ] …]:指定Intent category,實現原理Intent.addCategory()
● -p : 指定包名,實現原理Intent.setPackage();
● -f : 添加flags,實現原理Intent.setFlags(int ),緊接着的參數必須是int型;

基本類型
參數-e/-es-esn-ez-ei-el-ef-eu-ecn類型String(String)nullbooleanintlongfloaturicomponent
比如參數es是Extra String首字母簡稱,實例:
intent.putExtra(“website”,“website gityuan.com”)
am start -n com.dongnao.app/.MainActivity -es website gityuan.com

intent.put

比如參數efal,是Extra float Array List首字母簡稱,多個value值之間以逗號隔開,實例:
am start -n comdongnao.app/.MainActivity -efal nums 1.2,2.2
此處-es website gityuan.com,等價於Intent.putExtra(“website”, “gityuan.com”);

AM四大組件 所有跳轉問題
AM 命令
跳轉 模塊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章