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以下
}