一、簡介:
StrictMode類是Android 2.3 (API 9)引入的一個工具類,可以用來幫助開發(fā)者發(fā)現(xiàn)代碼中的一些不規(guī)范的問題,以達(dá)到提升應(yīng)用響應(yīng)能力的目的。舉個例子來說,如果開發(fā)者在UI線程中進(jìn)行了網(wǎng)絡(luò)操作或者文件系統(tǒng)的操作,而這些緩慢的操作會嚴(yán)重影響應(yīng)用的響應(yīng)能力,甚至出現(xiàn)ANR對話框。為了在開發(fā)中發(fā)現(xiàn)這些容易忽略的問題,我們使用StrictMode,系統(tǒng)檢測出主線程違例的情況并做出相應(yīng)的反應(yīng),最終幫助開發(fā)者優(yōu)化和改善代碼邏輯。
二、官網(wǎng)文檔:StrictMode使用文檔
三、用途:
使用嚴(yán)格模式,系統(tǒng)檢測出主線程違例的情況會做出相應(yīng)的反應(yīng),如日志打印,彈出對話框亦或者崩潰等。換言之,嚴(yán)格模式會用不同的策略對應(yīng)用的違例細(xì)節(jié)做監(jiān)控,通過一定的方式暴露給開發(fā)者方便優(yōu)化與改善。
四、使用:
通常在Activity或者自定義的Application類的onCreate方法中啟動StrictMode(自定義application無效,不知道是不是配置問題)
// DEVELOPER_MODE代表只在調(diào)試模式下啟用StrictMode
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
}
StrictMode通過策略方式來讓你自定義需要檢查哪些方面的問題,主要有兩種策略:
ThreadPolicy:線程方面的策略
VmPolicy:VM方面的策略
ThreadPolicy策略:
StrictMode.ThreadPolicy.Builder主要方法如下:
detectNetwork():用于檢查UI線程中是否有網(wǎng)絡(luò)請求
detectDiskReads()和detectDiskWrites():是磁盤讀寫檢查
detectCustomSlowCalls():主要用于幫助開發(fā)者發(fā)現(xiàn)UI線程中調(diào)用的哪些方法執(zhí)行的比較慢,要和StrictMode.noteSlowCall配合使用,只有通過 StrictMode.noteSlowCall標(biāo)記“可能會”執(zhí)行比較慢的方法,只有標(biāo)記過的方法才能被檢測到,日志中會記錄方法的執(zhí)行時間(注意:只有在主線程中執(zhí)行的方法才會顯示執(zhí)行時間,在其他線程中執(zhí)行的方法,就算是使用StrictMode.noteSlowCall標(biāo)記,在日志中也不會打印執(zhí)行時間)
VMPloicy策略:
StrictMode.VmPolicy.Builder()主要方法如下:
detectActivityLeaks() 用戶檢查 Activity 的內(nèi)存泄露情況
detectLeakedClosableObjects() 和 detectLeakedSqlLiteObjects(),資源沒有正確關(guān)閉時回觸發(fā),detectLeakedSqlLiteObjects() 和 detectLeakedClosableObjects()的用法類似,只不過是用來檢查 SQLiteCursor 或者 其他 SQLite 對象是否被正確關(guān)閉
detectLeakedRegistrationObjects() 用來檢查 BroadcastReceiver 或者 ServiceConnection 注冊類對象是否被正確釋放
setClassInstanceLimit(),設(shè)置某個類的同時處于內(nèi)存中的實例上限,可以協(xié)助檢查內(nèi)存泄露
懲罰:
penaltyDeath():當(dāng)觸發(fā)違規(guī)條件時,直接Crash掉當(dāng)前應(yīng)用程序
penaltyDeathOnNetwork():當(dāng)觸發(fā)網(wǎng)絡(luò)違規(guī)時,Crash掉當(dāng)前應(yīng)用程序
penaltyDialog():觸發(fā)違規(guī)時,顯示對違規(guī)信息對話框
penaltyFlashScreen():會造成屏幕閃爍,不過一般的設(shè)備可能沒有這個功能
penaltyDropBox():將違規(guī)信息記錄到 dropbox 系統(tǒng)日志目錄中(/data/system/dropbox),你可以通過如下命令進(jìn)行插件
adb shell dumpsys dropbox dataappstrictmode --print
permitCustomSlowCalls()、permitDiskReads ()、permitDiskWrites()、permitNetwork: 如果你想關(guān)閉某一項檢測,可以使用對應(yīng)的permit*方法
最后:我們也可以在Android設(shè)備的設(shè)置(Settings)中啟用StrictMode(親測沒有什么效果):
開發(fā)者選項 > 啟用嚴(yán)格模式
最后分享一個小例子:
public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build());
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
writeToExternalStorage();
}
});
}
/**
* 文件系統(tǒng)的操作
*/
public void writeToExternalStorage() {
try {
File externalStorage = Environment.getExternalStorageDirectory();
File mbFile = new File(externalStorage, "xxx.txt");
if (mbFile.exists()){
mbFile.createNewFile();
}
OutputStream output = new FileOutputStream(mbFile, true);
output.write("www.wooyun.org".getBytes());
output.flush();
output.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
使用penaltyLog():
D/StrictMode: StrictMode policy violation; ~duration=3 ms: android.os.StrictMode$StrictModeDiskWriteViolation: policy=65567 violation=1
at android.os.StrictMode$AndroidBlockGuardPolicy.onWriteToDisk(StrictMode.java:1253)
at java.io.FileOutputStream.<init>(FileOutputStream.java:220)
at com.perf.strictmodedemo.MainActivity.writeToExternalStorage(MainActivity.java:44)
at com.perf.strictmodedemo.MainActivity$1.onClick(MainActivity.java:28)
at android.view.View.performClick(View.java:5619)
at android.view.View$PerformClick.run(View.java:22298)
at android.os.Handler.handleCallback(Handler.java:754)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:165)
at android.app.ActivityThread.main(ActivityThread.java:6365)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:883)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
使用penaltyDialog():

筆者使用后感覺,StrictMode適合作為一些基礎(chǔ)規(guī)范問題排查。