中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

android監聽應用是否被卸載的方法

發布時間:2020-06-05 15:27:23 來源:億速云 閱讀:494 作者:Leah 欄目:移動開發

這篇文章主要介紹了android監聽應用是否被卸載的方法,具有一定借鑒價值,需要的朋友可以參考下。如下資料是關于android實現監聽的詳細步驟內容。

一  效果演示


    打開應用效果圖:

android監聽應用是否被卸載的方法

    圖1


    點擊卸載后提示,如下圖:

android監聽應用是否被卸載的方法

    圖2

    然后退出應用,卸載程序,會發現當應用被卸載以后,會彈出調用瀏覽器的提示,這里隨便放了一個搜狐瀏覽頁面,在自己的應用中應該調用的一般都是調查頁面。如下圖:

android監聽應用是否被卸載的方法

    圖3


    ok,效果前面已經演示了,現在需要討論一下其具體實現了。

    首先,通過adb shell進入手機,然后第一次進入應用,像圖1一樣,不點擊按鈕,通過 ps | busybox grep ubuntu 看這個應用的進程信息,如下圖:

android監聽應用是否被卸載的方法

   這個時候只有

   u0_a108   2953  124   490956 47792 ffffffff 40052a40 S com.example.ubuntuforandroid
   2953 這一個進程


   點擊 卸載后提示 按鈕再次,執行剛才執行的ps命令,發現已經有兩個進程了如下圖:

android監聽應用是否被卸載的方法


  其實新產生的進程是通過程序調用jni接口


public static native int Reguninstall(String path,String url);


  這個接口fork了一個進程,而新fork的進程負責監聽本應用是否被卸載了


二  源碼分析


  java層的代碼如下,很簡單,就是調用一下jni接口


protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
                                                                                                                                                                                                                                                                                                      
    setContentView(R.layout.activity_main);
                                                                                                                                                                                                                                                                                              
    initInjectFunction("testfile");
                                                                                                                                                                                                                                                                                              
    test = (TextView)this.findViewById(R.id.testview);
    test.setText("點擊卸載后提示按鈕,你的應用在卸載以后會調用瀏覽器,然后調用你需要的頁面。");
                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                     
    btn = (Button)this.findViewById(R.id.testbtn);
    btn.setOnClickListener(new View.OnClickListener() {
                                                                                                                                                                                                                                                                                                  
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            String directory = MainActivity.this.getFilesDir().getAbsolutePath();
            String url = "http://www.sohu.com/";
            JniExec.Reguninstall(directory,url);
            test.setText("現在可以退出應用,然后卸載應用,看看是否有效果");
        }
    });
                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                            
}


一目了然,不用多言了


   現在就分析

package com.example.ubuntuforandroid;
public class JniExec {
    static {
        System.loadLibrary("uninstall");
    }
                                                                                                                                                                                                                                                                                     
    public static native int Reguninstall(String path,String url);
                                                                                                                                                                                                                                                                                     
}

 Reguninstall 這個jni接口里面做了什么事情,能夠達到監聽本身應用卸載的效果。


  native代碼分析


jint Java_com_example_ubuntuforandroid_JniExec_Reguninstall(JNIEnv* env, jobject thiz, jstring path,
        jstring url)
{
    LOGI("Java_com_example_ubuntuforandroid_JniExec_Reguninstall");
    char *listenpath = (char*) (*env)->GetStringUTFChars(env,path, 0);
    char *jumpurl = (char*) (*env)->GetStringUTFChars(env,url, 0);
    LOGI("notify path is  %s",listenpath);
    LOGI("jumpurl  is  %s",jumpurl);
    pid_t pid;
    pid = fork();
    if(pid == 0)
    {
        //子進程
        inotify_main(listenpath,jumpurl);
    }
    //父進程不阻塞調用 waitpid  ok 子進程變成了孤兒進程,被init進程收養了
    pid = waitpid(-1,0,1);
    LOGI("father bye bye");
    return 0;
}


這個接口里面最關鍵的是調用了 inotify_main 這個函數。如果看這段代碼比較費力的話,建議先弄清楚linux 下的fork機制,搞清楚 孤兒進程 僵尸進程這些如何產生的情況。


下面看   inotify_main 這個函數

void inotify_main(char *path,char *url)
{
    struct pollfd poll_list[2];
    poll_list[0].fd = inotify_init();
    poll_list[0].events = POLLIN;
    int wd = inotify_add_watch(poll_list[0].fd, path, IN_DELETE | IN_CREATE);
    if(wd < 0) {
        fprintf(stderr, "could not add watch for %s, %s\n", path, strerror(errno));
        return ;
    }
    int retval;
    while(1)
    {
        retval = poll(poll_list,(unsigned long)1,-1);
        /* retval 總是大于0或為-1,因為我們在阻塞中工作 */
        LOGI("retval = %d\n",retval);
        if(retval < 0)
        {
            fprintf(stderr,"poll錯誤: %s/n",strerror(errno));
            return;
        }
        if((poll_list[0].revents & POLLIN) == POLLIN)
        {
          LOGI("poll_list[0].revents&POLLIN\n");
          inotify_handle(poll_list[0].fd,url);
        }
    }
     inotify_rm_watch(poll_list[0].fd,wd);
}


這個函數,這里面用到了  inotify_init  inotify_add_watch  inotify_rm_watch 這幾個linux接口,這幾個接口主要的作用就是監聽指定的目錄,其配合poll函數,能夠監聽目錄下的任何改動,當要監聽的目錄有任何改動的時候,會觸發poll函數的 POLLIN 有可讀數據到來事件。


在本應用中,監聽的是 /data/data/com.example.ubuntuforandroid/files/ 這個目錄,因為在卸載的時候卸載程序會刪除監聽目錄的,而fork出來的守護進程當發現自身應用的目錄被卸載程序刪除了也就是卸載了,這個時候調用 inotify_handle 這個函數,然后調用 am命令啟動瀏覽器,調用自己需要調用界面。


當然,在調用am指令以后,記得自身守護進程的使命也完成了,需要exit退出一下。

inotify接口的用處很多,擴展一下,也可以用于守護進程,比如A進程和B進程是共生共死的,這里有一種實現的方式就是 A進程用inotify 監聽 /proc/B進程id目錄,當B進程結束的時候,A進程就能知道B進程不在了,從而結束自己。

上文描述的就是android監聽應用是否被卸載的方法,具體使用情況還需要大家自己動手實驗使用過才能領會。如果想了解更多相關內容,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

咸阳市| 法库县| 四平市| 东乡族自治县| 济源市| 聊城市| 南皮县| 广灵县| 晋宁县| 淮阳县| 古交市| 南溪县| 永丰县| 浪卡子县| 宜良县| 手机| 壶关县| 清远市| 二手房| 安国市| 阜宁县| 高安市| 星子县| 江津市| 永清县| 历史| 天峻县| 伊川县| 汕头市| 土默特右旗| 客服| 泸西县| 长沙市| 太仆寺旗| 巴塘县| 上思县| 慈溪市| 微博| 曲阜市| 四会市| 阳泉市|