`
深海的鱼
  • 浏览: 13724 次
社区版块
存档分类
最新评论

StrictMode 严苛模式

阅读更多

Android 2.3提供一个称为严苛模式(StrictMode)的调试特性,Google称该特性已经使数百个Android上的Google应用程序受益。那它都做什么呢?它将报告与线程及虚拟机相关的策略违例。一旦检测到策略违例(policy violation),你将获得警告,其包含了一个栈trace显示你的应用在何处发生违例。你可以强制用警告代替崩溃(crash),也可以仅将警告计入日志,让你的应用继续执行。策略的细节尚难确定,可以期待随Android的成熟Google将增加更多策略。

    目前有2种策略可用,第一个和线程相关,它主要针对主线程(或UI线程)。由于在主线程中读写磁盘和进行网络访问都不是好的做法,Google已经在磁盘和网络代码中添加了严苛模式(StrictMode)钩子(hook)。如果你对某个线程打开严苛模式(StrictMode),当那个线程进行磁盘和网络访问,你将获得警告。你可以选择警告方式。一些违例包含用户慢速调用(custom slow calls 这么翻译行吗?),磁盘读写,网络访问。你能选择将警告写入LogCat,显示一个对话框,闪下屏幕,写入DropBox日志文件,或让应用崩溃。最通常的做法是写入LogCat或让应用崩溃。列表2-9显示了一个为线程策略设置严苛模式(StrictMode)的例子。

列表2-9 设置严苛模式(StrictMode)的线程策略

[java] view plaincopy
  1. StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()  
  2.     .detectDiskReads()  
  3.     .detectDiskWrites()  
  4.     .detectNetwork()  
  5.     .penaltyLog()  
  6.     .build());  

    Builder类使得设置变得很简单,Builder函数定义所有策略都返回Builder对象,从而这些函数能像列表2-9那样串连在一起。最后调用build()函数返回一个ThreadPolicy对象作为StrictMode对象的setThreadPolicy()函数的参数。注意到setThreadPolicy()是一个静态函数,因此不需要实例化StrictMode对象。在内部,setThreadPolicy()将对当前线程应用该策略。如果不指定检测函数,也可以用detectAll()来替代。penaltyLog()表示将警告输出到LogCat,你也可以使用其他或增加新的惩罚(penalty)函数,例如使用penaltyDeath()的话,一旦StrictMode消息被写到LogCat后应用就会崩溃。

    你不需要频繁打开严苛模式(StrictMode),你可以在主活动的onCreate()函数中打开它,你也可以在Application派生类的OnCreate()函数中设置严苛模式(StrictMode)。线程中运行的任何代码都可以设置严苛模式(StrictMode),但你的确只需要设置一次,一次就够了。

    类似于线程策略(ThreadPolicy),严苛模式(StrictMode)有虚拟机策略(VmPolicy)。虚拟机策略(VmPolicy)能检查内存泄漏,譬如,当关闭一个SQLite对象前的完结操作,或其他任何类似可关闭对象在关闭前的完结操作。虚拟机策略(VmPolicy)由一个类似的Builder类创建,如列表2-10所示。和线程策略(ThreadPolicy)不同的是,虚拟机策略(VmPolicy)不能通过一个对话框提供警告。

列表2-10 设置严苛模式(StrictMode)的虚拟机策略

 

[java] view plaincopy
  1. StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()  
  2.     .detectLeakedSqlLiteObjects()  
  3.     .penaltyLog()  
  4.     .penaltyDeath()  
  5.     .build());  

    因为设置发生在线程中,严苛模式(StrictMode)甚至能在从一个对象到另一个对象的控制流中找到违例事件。当违例发生,你会惊奇地注意到代码正运行于主线程,而栈trace将帮助你发现它如何发生。于是你能单步调试解决问题,或是将代码移到它自己的后台线程,或是就保持原来的处理方式。这都取决与你。当然,你可能希望适时关闭严苛模式(StrictMode),当你的程序作为产品发布时,你可不希望它仅为了一个警告在你的用户手里崩溃。

    有两个方法可以关闭严苛模式(StrictMode),最直接的就是移除相应代码,但这样做不利于持续开发的产品。你通常可以定义一个应用级别布尔变量来测试是否需要调用严苛模式(StrictMode)代码。在发布产品前将这个值定义为FALSE。更优雅的方式是利用调试模式(debug mode)的特点,在AndroidManifest.xml中定义这个布尔变量。<application>字段的属性之一是android:debuggable,其义自明。列表2-11给出了利用该特性的控释方法。

 

列表2-11 仅在调试模式设置严苛模式(StrictMode)

 

[java] view plaincopy
  1. // Return if this application is not in debug mode  
  2. ApplicationInfo appInfo = context.getApplicationInfo();  
  3. int appFlags = appInfo.flags;  
  4. if ((appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {  
  5.     // Do StrictMode setup here  
  6.     StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()  
  7.         .detectLeakedSqlLiteObjects()  
  8.         .penaltyLog()  
  9.         .penaltyDeath()  
  10.         .build());  
  11. }  

    使用Eclipse调试环境,ADT自动为你设置debuggable属性,使项目更易于管理。当你在模拟器上或直接在设备上部署应用,debuggable属性为TRUE,当你导出应用建立一个产品版本,ADT将该属性置为FALSE。注意,如果你另行设置了这个属性值,ADT不会改变它。

 

    严苛模式(StrictMode)很不错,不过在Android 2.3之前的版本上该模式不工作。为了避免这个问题,你要在StrictMode对象还不存在的时候就验证版本是否在Android2.3及以上。你能利用反射技术(reflection),当严苛模式(StrictMode)函数有效时间接调用它,反之不去调用。方法很简单,你能按列表2-12中的代码处理

列表2-12  利用反射技术(reflection)调用严苛模式(StrictMode)

 

[java] view plaincopy
  1. try {  
  2.     Class sMode = Class.forName("android.os.StrictMode");  
  3.     Method enableDefaults = sMode.getMethod("enableDefaults");  
  4.     enableDefaults.invoke(null);  
  5. }  
  6. catch(Exception e) {  
  7.     // StrictMode not supported on this device, punt  
  8.     Log.v("StrictMode""... not supported. Skipping...");  
  9. }  

    当严苛模式(StrictMode)不存在,将捕捉到ClassNotFoundException异常。enableDefault()是严苛模式(StrictMode)类的另一个函数,它检测所有违例并写入LogCat。因为这里调用的是静态形式的enableDefault(),所以用null作为参数传入。

 

    某些时候你不希望报告所有违例。那在主线程之外的其他线程中设置严苛模式(StrictMode)很不错。譬如,你需要在正在监视的线程中进行磁盘读取。此时,你要么不去调用detectDiskReads(),要么在调用detectAll()之后跟一个permitDiskReads()。类似允许函数也适用于其他操作。但要是你要在Anroid2.3之前版本上做这些事,有办法吗?当然有。

    当应用中严苛模式(StrictMode)无效,如果你试图访问它,将抛出一个VerifyError异常。如果你将严苛模式(StrictMode)封装在一个类里,并捕捉这个错误,当严苛模式(StrictMode)无效时,你能忽略它。列表2-13显示一个简单的严苛模式(StrictMode)封装类StrictModeWrapper。列表2-14显示了如何在你的应用中使用这个封装类。

列表 2–13 在Anroid2.3之前版本建立严苛模式(StrictMode)封装类

 

[java] view plaincopy
  1. import android.content.Context;  
  2. import android.content.pm.ApplicationInfo;  
  3. import android.os.StrictMode;  
  4. public class StrictModeWrapper {  
  5.     public static void init(Context context) {  
  6.         // check if android:debuggable is set to true  
  7.         int appFlags = context.getApplicationInfo().flags;  
  8.         if ((appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {  
  9.             StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()  
  10.                 .detectDiskReads()  
  11.                 .detectDiskWrites()  
  12.                 .detectNetwork()  
  13.                 .penaltyLog()  
  14.                 .build());  
  15.             StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()  
  16.                 .detectLeakedSqlLiteObjects()  
  17.                 .penaltyLog()  
  18.                 .penaltyDeath()  
  19.                 .build());  
  20.         }  
  21.     }  
  22. }  


列表 2–14  在Anroid2.3之前版本调用严苛模式(StrictMode)封装类

 

[java] view plaincopy
  1. try {  
  2.     StrictModeWrapper.init(this);  
  3. }  
  4. catch(Throwable throwable) {  
分享到:
评论

相关推荐

    Android StrictMode运行流程(推荐)

    什么是 StrictMode(严苛模式) strictmode是android在 API9后引入的检测影响app运行流畅性的一种机制,例如我们都知道的主线程中不允许有网络操作这条规则就是严苛模式规则的一种. strictmode.java 这个类中设定了许多...

    详解Android StrictMode严格模式的使用方法

    在使用StrictMode时,不需要频繁打开严苛模式,可以在Activity的onCreate()函数中打开它,也可以在Application派生类的OnCreate()函数中设置严苛模式。线程中运行的任何代码都可以设置严苛模式,但你的确只需要设置...

    strictMode介绍

    StrictMode是自Android 2.3(Gingerbread)版本起引入的一个功能,它作为开发者模式的一部分,为应用程序提供了一种检测和报告应用行为中潜在问题的机制。通过启用StrictMode,开发者可以监控并捕获应用在运行时可能...

    Android性能调优利器StrictMode应用分析

    StrictMode意思为严格模式,是用来检测程序中违例情况的开发者工具。最常用的场景就是检测主线程中本地磁盘和网络读写等耗时的操作。 严在哪里 既然叫做严格模式,那么又严格在哪些地方呢? 在Android中,主线程,也

    StrictModeUtils.java

    严苛模式主要检测两大问题,一个是线程策略,即TreadPolicy,另一个是VM策略,即VmPolicy。 常见用法 严格模式的开启可以放在Application或者Activity以及其他组件的onCreate方法。为了更好地分析应用中的问题,...

    android strictmode_dropbox_tombstone介绍

    介绍android 上运行时调试工具,strictmode,dropbox和tombstone

    Android HttpURLConnection中 StrictMode同时支持3.0以上和3.0以下版本

    `StrictMode`是一个调试工具,它允许开发者在应用程序中开启一个严格的执行模式,当检测到违反规则的行为(如在主线程中进行IO操作)时,会触发惩罚策略,如打印日志、显示对话框或终止应用。在Android 3.0及以上...

    Eclipse错误解决方法

    当出现提示说: Call requires API level 9 (current min is 8): android.os.StrictMode#setThrea 也就是说版本低

    Android代码-用 RxJava 实现 EventBus 。

    StrictMode 宽泛匹配模式 严格匹配模式 StickyEvent @BusEvent 实现教程 关于作者 联系方式 开源项目 License 基于发布订阅(Pub/Sub)模式的一个事件消息库,使用通用的 register(target), unregister(target...

    android7.0严格模式兼容

    首先,Android 7.0引入了"StrictMode",这是一个针对开发者工具的API,它可以帮助开发者在应用运行时检测到潜在的问题,如主线程上的磁盘读写、网络访问、长时间运行的后台操作等。在严格模式下,这些问题会触发惩罚...

    Android 7.0行为变更 FileUriExposedException解决方法

    Android 7.0行为变更 ...对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI。如果一项包含文件 URI 的 intent 离开您的应用,则应用出现故障,并出现 FileUriE

    web-audio-hooks-issue:用于调试React StrictMode与useAudioContext的交互

    在开发模式下运行应用程序。 打开在浏览器中查看它。 如果您进行编辑,则页面将重新加载。 您还将在控制台中看到任何棉绒错误。 npm test 在交互式监视模式下启动测试运行器。 有关更多信息,请参见关于的部分。 ...

    StrictModeTest

    严格模式(StrictMode)是Java开发中的一种工具,主要用于在应用程序中检测并防止潜在的性能问题、资源泄漏和不安全的操作。它通过运行时检查来提醒开发者可能存在的问题,帮助优化代码并提升应用的稳定性。在Android...

    Android通过webservice连接SqlServer实例(Android4.0可运行)

    Android通过webservice连接SqlServer实例(Android4.0可运行)从原博http://blog.csdn.net/zhyl8157121/article/details/8169172下载下来的demo,看了评论和其它文章后修改,解决了Android2.3以上StrictMode模式下不...

Global site tag (gtag.js) - Google Analytics