1. 程式人生 > >android 如何實現一鍵清理

android 如何實現一鍵清理

 從事android系統開發有一段時間,一直在想著能夠有一些內容能夠與朋友們分享;同時,也能夠再一次的加深之前解決的問題和原理!開發過程中有時也是通過搜尋各種資料和閱讀各位博主的文章,解決了遇到的問題;在此,也對各位博主和大神表示感謝,這也是我想寫部落格的原因,不能一直是"拿來主義"!
 先寫一個比較簡單的例子當作開端!
 問題描述:在一次客戶定製的機器上有一音樂apk,在點選最近任務介面的"X"號退出之後仍然能夠播放歌曲
 ![一鍵清理圖](https://img-blog.csdn.net/20170913211629401?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTWljaGFlbDMxMjkxNw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

解決方案:X號的資源id為dismiss_task,原始碼位於frameworks\base\packages\SystemUI\src\com\android\systemui\recents\views\TaskViewHeader.java
該按鍵的點選事件在該類中的

      @Override
    public void onClick(View v) {
        if (v == mIconView) {
            EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
} else if (v == mDismissButton) { **ActivityManager activityManager = (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);* TaskView tv = Utilities.findParent(this, TaskView.class); tv.dismissTask();* **if("清理app的title"
.equalsIgnoreCase(mTitleView.getText().toString())){ activityManager.forceStopPackage("清理app的包名");* }* // Keep track of deletions by the dismiss button MetricsLogger.histogram(getContext(), "overview_task_dismissed_source", Constants.Metrics.DismissSourceHeaderButton); } ............. }

只需要呼叫ActivityManager的forceStopPackage(String pkgName)方法即可,該函式是系統隱藏函式,其作用是:強制終止指定的apk,包括apk所在的程序及service,並且終止service不會被當做crash而被系統重新啟動起來;因此使用該函式限制因素有:1.整合的app必須放置到system/app或者priv-app 2.具有系統簽名
重新編譯SystemUI驗證,可以發現功能雖然可以,但是還是存在問題;如果切換語言的話,會導致“清理app的title”變成相應的語言,還是不起作用;那麼在TaskViewHeader.java檔案中檢視是否有獲取App相關資訊函式;是否有任務棧之類的變數呢?仔細檢視程式碼,在該mDismissButton上方的mIconView中有一個Task mTask全域性變數,frameworks\base\packages\SystemUI\src\com\android\systemui\recents\model\Task.java
檢視該類,很明顯的看到該類有一個getComponent()的方法,能夠返回應用的元件名;因此完全可以通過獲取的元件名,再獲得相應的包名既可以完全解決該問題。
如何獲得getComponent()方法呢?該方法是Task中TaskKey的內部類的方法;TaskKey又是Task的公共的全域性變數,那麼可以通過mTask獲取到對應的TaskKey屬性,再由TaskKey呼叫getComponent()就可以完全解決!
修改上述程式碼如下:

        ComponentName cn = mTask.key.getComponent();
            String pkgName = cn.getPackageName();  //獲取包名
             String className = ngetClassName();     //獲取類名
            if("清理app的類名".equalsIgnoreCase(pkgName)){
                activityManager.forceStopPackage("清理app的類名");
        }
其實通過做android系統開發,有些問題主要是考慮到系統是否有類似的功能和對應的函式,這也就要求我們有時對原始碼有個大致的印象,能夠定位到問題點、相應的系統函式或者系統功能,完成自己所需要的功能和問題的解決方案!