StrictMode總結

Android 2.3提供一個稱爲嚴苛模式(StrictMode)的調試特性,Google稱該特性已經使數百個Android上的Google應用程序受益。

首先先整體介紹:

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()//線程策略(ThreadPolicy)
                    .detectDiskReads()//檢測在UI線程讀磁盤操作
                    .detectDiskWrites()//檢測UI線程寫磁盤操作
                    .detectCustomSlowCalls()//發現UI線程調用的哪些方法執行得比較慢
                    .detectResourceMismatches()//最低版本爲API23  發現資源不匹配
                    .detectNetwork() //檢測在UI線程執行網絡操作
                    .penaltyDialog()//一旦檢測到彈出Dialog
                    .penaltyDeath()//一旦檢測到應用就會崩潰
                    .penaltyFlashScreen()//一旦檢測到應用將閃屏退出 有的設備不支持
                    .penaltyDeathOnNetwork()//一旦檢測到應用就會崩潰
                    .penaltyDropBox()//一旦檢測到將信息存到DropBox文件夾中 data/system/dropbox
                    .penaltyLog()//一旦檢測到將信息以LogCat的形式打印出來
                    .permitDiskReads()//允許UI線程在磁盤上讀操作
                    .build());
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()//虛擬機策略(VmPolicy)
                    .detectActivityLeaks()//最低版本API11 用戶檢查 Activity 的內存泄露情況
                    .detectCleartextNetwork()//最低版本爲API23  檢測明文的網絡
                    .detectFileUriExposure()//最低版本爲API18   檢測file://或者是content://
                    .detectLeakedClosableObjects()//最低版本API11  資源沒有正確關閉時觸發
                    .detectLeakedRegistrationObjects()//最低版本API16  BroadcastReceiver、ServiceConnection是否被釋放
                    .detectLeakedSqlLiteObjects()//最低版本API9   資源沒有正確關閉時回觸發
                    .setClassInstanceLimit(MyClass.class, 2)//設置某個類的同時處於內存中的實例上限,可以協助檢查內存泄露
                    .penaltyLog()//與上面的一致
                    .penaltyDeath()
                    .build());

一 線程策略

detectDiskReads()/detectDiskWrites操作示例:

       StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectDiskWrites()
                .detectDiskReads()
                .penaltyLog()
                .build());

        strictReads();
        
    }

    private void strictReads(){
        File file = new File(Environment.getExternalStorageDirectory().getPath()+"/note.txt");
        FileInputStream inputStream = null;
        int r = -1;
        try {
            inputStream = new FileInputStream(file);
            while((r = inputStream.read()) != -1){
                
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

detectCustomSlowCalls操作示例:

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectCustomSlowCalls()
                .penaltyLog()
                .build());

        showCustomSlowCallFlag();
        showCustomSlowCall();

    }

    private void showCustomSlowCallFlag(){
        StrictMode.noteSlowCall("This is Andly");
        SystemClock.sleep(10002);
    }

    private void showCustomSlowCall(){
        SystemClock.sleep(10002);
    }
Log:(只有作了標記得纔會打印log)


detectResourceMismatches操作示例:

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectResourceMismatches()
                .penaltyLog()
                .build());

        showResourceMismatches();

    }

    private void showResourceMismatches() {
        TypedArray ta = getResources().obtainTypedArray(R.array.icons);
        int a = ta.getInt(0,0);
    }
這個沒有打印log,不知道爲什麼。。

detectNetwork操作示例:

  StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectNetwork()
                .penaltyLog()
                .build());

        strictNetWork();
    }

    private void strictNetWork(){
        try {
            URL url = new URL("http://www.baidu.com");
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.connect();
            httpURLConnection.setRequestMethod("GET");
            httpURLConnection.setReadTimeout(3000);
            httpURLConnection.setConnectTimeout(5000);
            int code = httpURLConnection.getResponseCode();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

log:

對於線程策略剩下的比較簡單就不多說,然後介紹一下:使用penaltyDropBox想要看文件得信息只需要輸入:

adb shell dumpsys dropbox (這裏寫data/system/dropbox目錄下文件的名字) --print

二 VM策略

detectActivityLeaks操作示例:

StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectActivityLeaks()
                .penaltyLog()
                .penaltyDropBox()
                .build());


        new Thread(new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(1000);
            }
        }).start();
    }
log:


log上面顯示,實例創建了2個但是限制的是一個
detectLeakedClosableObjects操作示例:

StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectLeakedClosableObjects()
                .penaltyLog()
                .penaltyDropBox()
                .build());

        leakedClosableObj();

    }

    private void leakedClosableObj() {
        File newxmlfile = new File(Environment.getExternalStorageDirectory(), "/note.txt");
        try {
            newxmlfile.createNewFile();
            FileWriter fw = new FileWriter(newxmlfile);
            fw.write("Andly");
            //fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

setClassInstanceLimit操作示例:

StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .setClassInstanceLimit(LimitClass.class, 2)
                .penaltyLog()
                .penaltyDropBox()
                .build());

        classInstanceLimit();
    }

    private void classInstanceLimit() {
        classList.add(new LimitClass());
        classList.add(new LimitClass());
        classList.add(new LimitClass());
        classList.add(new LimitClass());
        classList.add(new LimitClass());
        classList.add(new LimitClass());
    }
log:


detectLeakedRegistrationObjects操作示例:

StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectLeakedRegistrationObjects()
                .penaltyLog()
                .penaltyDropBox()
                .build());

        leakeRegistion();
    }

    private void leakeRegistion() {
        receiver = new myReceive();
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.andly.broadcast");
        registerReceiver(receiver,filter);
    }
log:


考慮倒關於版本兼容問題,因爲按照上面的寫法在2.3以下系統是沒有問題的,但是在2.3以上的話,就會出錯,所以應該採用以下方式來處理

try {
            Class clazz = Class.forName("android.os.StrictMode");
            ApplicationInfo info = getApplicationInfo();
            if((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0){
                //可以使用嚴苛模式
            }else{
                //不可使用嚴苛
            }
        } catch (ClassNotFoundException e) {
            //StrictMode類不可用  用這種方法來判斷是否再Android2.3以下
        }


發佈了59 篇原創文章 · 獲贊 10 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章