StrictMode使用详解

StrictMode使用详解StrictMode    StrictMode最常用来捕捉应用程序的主线程,它将报告与线程及虚拟机相关的策略违例。一旦检测到策略违例(policyviolation),你将获得警告,其包含了一个栈trace显示你的应用在何处发生违例。除了主线程,我们还可以在Handler,AsyncTask,AsyncQueryHandler,IntentService等API中使用StrictMod

大家好,又见面了,我是你们的朋友全栈君。

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后应用就会崩溃。具体支持的监视方法见:https://developer.android.com/reference/android/os/StrictMode.ThreadPolicy.Builder.htmlhttps://developer.android.com/reference/android/os/StrictMode.VmPolicy.Builder.html

         在正式版本中,我们并不希望使用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使用详解

暂停监测

如果在程序运行中无法避免的会违反StrictMode中的一些定义好的策略,而我们又希望能够暂时忽略这些策略的监视,我们可以使用permitXXXXX方法来暂停这些内容的监测,在做完需要忽略的监测之后,再起用监测,代码如下所示:

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

代码下载:Github   欢迎frok、star、follow

我的视频教程:我的视频教程

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/133159.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • CString 使用详解

    CString 使用详解CString::MakeUppervoidMakeUpper();Remarks备注ConvertsthisCStringobjecttoanuppercasestring.将原对

  • netstat 命令详解

    netstat 命令详解netstat命令是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息。语法选项netstat[选项]-a或–all:显示所有连线中的Socket;-A<网络类型>或–<网络类型>:列出该网络类型连线中的相关地址;

  • 【搜索】八皇后「建议收藏」

    【搜索】八皇后「建议收藏」这道题应该不陌生吧,这是一道很经典的搜索题。总的意思就是说在一个n*n的棋盘上放n个皇后,要求它们互不攻击,求解有多少种情况,并输出前三种。那么开始分析:这毕竟是一道搜索题,搜索最大的弊端是什么,

  • px2rem配置_px和rem转换器

    px2rem配置_px和rem转换器安装px2rem后,再使用px上有些不同,大家可以参考px2rem官方介绍,下面简单介绍一下。直接写px,编译后会直接转化成rem—-除开下面两种情况,其他长度用这个在px后面添加/*no*/,不会转化px,会原样输出。—一般border需用这个在px后面添加/*px*/,会根据dpr的不同,生成三套代码。—-一般字体需用这个 …

    2022年10月23日
  • python 写入文件时编码问题

    python 写入文件时编码问题本文仅供学习交流使用,如侵立删!联系方式及demo下载见文末python写入文件时编码错误UnicodeDecodeError:’utf-8’codeccan’tdecodebyte..解决:增加errors=‘ignore’withopen(‘数据.csv’,”r”,encoding=’utf-8′,errors=’ignore’,newline=””)asf1:本文仅供学习交流使用,如侵立删!企鹅、WX:1033383881(备注来意)

  • 人工智能马尔可夫模型_高斯马尔科夫模型

    人工智能马尔可夫模型_高斯马尔科夫模型(马尔可夫与马尔科夫都可以,所以也别纠结)马尔可夫模型(MarkovModel)是一种统计模型,广泛应用在语音识别,词性自动标注,音字转换,概率文法等各个自然语言处理等应用领域。经过长期发展,尤其是在语音识别中的成功应用,使它成为一种通用的统计工具。      ———–百度对于马尔科夫实际上是根据根据历史数据和其中的规律,总结出变化的规律,使用概率转移图的形式来推断…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号