程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> StrictMode使用詳解

StrictMode使用詳解

編輯:關於C++

StrictMode

StrictMode最常用來捕捉應用程序的主線程,它將報告與線程及虛擬機相關的策略違例。一旦檢測到策略違例(policy violation),你將獲得警告,其包含了一個棧trace顯示你的應用在何處發生違例。除了主線程,我們還可以在Handler,AsyncTask,AsyncQueryHandler,IntentService等API中使用StrictMode。

檢查策略

StrictMode的線程策略主要用於檢測磁盤IO和網絡訪問,而虛擬機策略主要用於檢測內存洩漏現象。Android已經在磁盤IO訪問和網絡訪問的代碼中已經加入了StrictMode。當監視的線程發生策略的違例時,就可以獲得警告,例如寫入LogCat,顯示一個對話框,閃下屏幕,寫入DropBox日志文件,或讓應用崩潰。最通常的做法是寫入LogCat或讓應用崩潰。下面的代碼展示了如何使用StrictMode的檢查策略:

 

public void onCreate() {
     if (DEVELOPER_MODE) {
         StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                 .detectDiskReads()
                 .detectDiskWrites()
                 .penaltyDialog()
                 .detectNetwork()   // or .detectAll() for all detectable problems
                 .penaltyLog()
                 .build());
         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                 .detectLeakedSqlLiteObjects()
                 .detectLeakedClosableObjects()
                 .penaltyLog()
                 .penaltyDeath()
                 .build());
     }
     super.onCreate();
 }

 

使用方法

如果不指定檢測函數,也可以用detectAll()來替代。penaltyLog()表示將警告輸出到LogCat,你也可以使用其他或增加新的懲罰(penalty)函數,例如使用penaltyDeath()的話,一旦StrictMode消息被寫到LogCat後應用就會崩潰。 

在正式版本中,我們並不希望使用StrictMode來讓用戶的應用因為一個警告而崩潰,所以在應用正式發布時,需要移出這些監視。你可以通過刪除代碼來實現,不過這裡提供一個更好的方式來解決這個問題,即使用AndroidMainifest文件中的debuggable屬性來實現,代碼如下所示:

 

android:debuggable=true

 

在代碼中,使用方法如下所示:

 

// Return if this application is not in debug mode 
ApplicationInfo appInfo = context.getApplicationInfo(); 
int appFlags = appInfo.flags; 
if ((appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { 
    // Do StrictMode setup here 
    StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() 
        .detectLeakedSqlLiteObjects() 
        .penaltyLog() 
        .penaltyDeath() 
        .build()); 
}

StrictMode實例

 

我們在測試代碼的主線程中去訪問網絡,這樣就一定會觸發StrictMode的線程監測,代碼如下所示:

 

public class MainActivity extends Activity {

    private HttpResponse httpResponse = null;
    private HttpEntity httpEntity = null;
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectDiskReads()
                .detectDiskWrites()
                .detectNetwork()
                .penaltyDialog()
                .penaltyLog()
                .build());
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = (TextView) findViewById(R.id.text);
        HttpGet httpGet = new HttpGet(http://www.baidu.com);
        HttpClient httpClient = new DefaultHttpClient();
        InputStream inputStream = null;
        try {
            httpResponse = httpClient.execute(httpGet);
            httpEntity = httpResponse.getEntity();
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                inputStream = httpEntity.getContent();
                BufferedReader reader = 
                      new BufferedReader(new InputStreamReader(inputStream));
                mTextView.setText(reader.readLine());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 

運行代碼,並將Log信息保存到本地,在Log中,我們可以搜索D/StrictMode(15454): StrictMode policy violation關鍵字。這裡截取一段,如下所示:


D/StrictMode(15454): StrictMode policy violation; ~duration=461 ms:
 android.os.StrictMode$StrictModeNetworkViolation: policy=55 violation=4
D/StrictMode(15454): 	at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1153)
D/StrictMode(15454): 	at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:249)
D/StrictMode(15454): 	at libcore.io.IoBridge.recvfrom(IoBridge.java:553)
D/StrictMode(15454): 	at java.net.PlainSocketImpl.read(PlainSocketImpl.java:485)
D/StrictMode(15454): 	at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37)
D/StrictMode(15454): 	at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
D/StrictMode(15454): 	at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:103)
D/StrictMode(15454): 	at org.apache.http.impl.io.AbstractSessionInputBuffer.read(AbstractSessionInputBuffer.java:134)
D/StrictMode(15454): 	at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:161)
D/StrictMode(15454): 	at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:175)
D/StrictMode(15454): 	at org.apache.http.impl.io.ChunkedInputStream.exhaustInputStream(ChunkedInputStream.java:289)
D/StrictMode(15454): 	at org.apache.http.impl.io.ChunkedInputStream.close(ChunkedInputStream.java:262)
D/StrictMode(15454): 	at org.apache.http.conn.BasicManagedEntity.streamClosed(BasicManagedEntity.java:179)
D/StrictMode(15454): 	at org.apache.http.conn.EofSensorInputStream.checkClose(EofSensorInputStream.java:266)
D/StrictMode(15454): 	at org.apache.http.conn.EofSensorInputStream.close(EofSensorInputStream.java:213)
D/StrictMode(15454): 	at com.imooc.strictmodetest.MainActivity.onCreate(MainActivity.java:53)
D/StrictMode(15454): 	at android.app.Activity.performCreate(Activity.java:5976)
D/StrictMode(15454): 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
D/StrictMode(15454): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2262)
D/StrictMode(15454): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2371)
D/StrictMode(15454): 	at android.app.ActivityThread.access$800(ActivityThread.java:149)
D/StrictMode(15454): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1289)
D/StrictMode(15454): 	at android.os.Handler.dispatchMessage(Handler.java:102)
D/StrictMode(15454): 	at android.os.Looper.loop(Looper.java:135)
D/StrictMode(15454): 	at android.app.ActivityThread.main(ActivityThread.java:5260)
D/StrictMode(15454): 	at java.lang.reflect.Method.invoke(Native Method)
D/StrictMode(15454): 	at java.lang.reflect.Method.invoke(Method.java:372)
D/StrictMode(15454): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
D/StrictMode(15454): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)

Log中可以顯示出StrictMode提示的原因,通過這裡的TraceLog我們就可以來找到優化的方法。除了在Logcat中查看StrictMode的日志信息,如果你使用了penaltyDropbox()方法,那麼你還可以通過如下所示的命令來調用DropBoxManager觀察StrictMode日志:

adb shell dumpsys dropbox data_app_strictmode --print

輸出日志文件如下所示:

========================================
2015-03-09 17:47:14 data_app_strictmode (text, 2177 bytes)
Process: com.imooc.strictmodetest
Flags: 0x88be46
Package: com.imooc.strictmodetest v1 (1.0)
Build: TCL/idol347/idol347:5.0.2/LRX22G/1040:userdebug/release-keys
System-App: false
Uptime-Millis: 389545133
Loop-Violation-Number: 4
Duration-Millis: 520
android.os.StrictMode$StrictModeNetworkViolation: policy=183 violation=4
	at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1153)
	at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
	at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
	at java.net.InetAddress.getAllByName(InetAddress.java:215)
	at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
	at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
	at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
	at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
	at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
	at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
	at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
	at com.imooc.strictmodetest.MainActivity.onCreate(MainActivity.java:43)
	at android.app.Activity.performCreate(Activity.java:5976)
	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2262)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2371)
	at android.app.ActivityThread.access$800(ActivityThread.java:149)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1289)
	at android.os.Handler.dispatchMessage(Handler.java:102)
	at android.os.Looper.loop(Looper.java:135)
	at android.app.ActivityThread.main(ActivityThread.java:5260)
	at java.lang.reflect.Method.invoke(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:372)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)

同時,如果使用了penaltyDialog()方法,在應用中還會彈出 提示框:

 

 

暫停監測

如果在程序運行中無法避免的會違反StrictMode中的一些定義好的策略,而我們又希望能夠暫時忽略這些策略的監視,我們可以使用permitXXXXX方法來暫停這些內容的監測,在做完需要忽略的監測之後,再起用監測,代碼如下所示:

 

 

StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(old)
        .permitDiskWrites()
        .build());
//doSomethingWriteToDisk();
StrictMode.setThreadPolicy(old);


 

 

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved