Android探索之旅 | StrictMode严苛模式

2023-10-20 08:59

本文主要是介绍Android探索之旅 | StrictMode严苛模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

-- 作者 谢恩铭 转载请注明出处

##StrictMode简介


StrictMode (android.os.StrictMode) 是一个自Android 2.3版(API 9。Gingerbread,姜饼)引入的类。

StrictMode是Strict和Mode的合并,在英语中,strict表示“严格的”,mode表示“模式”,因此,StrictMode就是“严格的模式”,或叫“严苛模式”。

既然是严苛的,那么肯定是对什么东西有限制。因为严格的老师肯定不会对坏学生纵容的,对吧,所以可以想见StrictMode是用来监测Android中的什么东西。

严苛的老师

是的,聪明如你果然猜对了。StrictMode就是用来指定一系列策略(policy),对相应规则(rule)进行检查并且做出反应。

这些策略大致包括Android的编码规范,例如监控在主线程(UI线程)中的操作,等等。

StrictMode有不同的策略,每种策略又用不同的规则(rule),每种规则又对应不同的方法,一旦规则被违反,这些对应的方法就会被用来做出反应。

注意 :

  • 在Debug模式启用StrictMode,别在Release模式启用。用户的小心脏是很脆弱的,假如一点点违规就导致应用崩溃,或者弹窗,那用户会把你的应用删除了。
  • 特别地, 调用JNI实现的磁盘读写操作和网络操作不会激活StrictMode。

##策略类型


目前,有两种类型的策略:

  • Thread Policy : 线程策略应用到特定的线程。
  • VM Policy : VM是Virtual Machine的缩写,表示“虚拟机”,不要搞错以为是Virtual Memory(虚拟内存)。应用于虚拟机进程中的所有线程。

ThreadPolicy.Builder中的一些方法:

  • detectAll() : 侦测一切潜在违规
  • detectCustomSlowCalls() : 侦测自定义的耗时操作
  • detectDiskReads() : 侦测磁盘读
  • detectDiskWrites() : 侦测磁盘写
  • detectNetwork() : 侦测网络操作
  • permitAll() : 禁用所有侦测
  • permitDiskReads() : 允许磁盘读

VmPolicy.Builder中的一些方法 :

  • detectAll() : 侦测一切潜在违规
  • detectActivityLeaks() : 侦测Activity(活动)泄露
  • detectLeakedClosableObjects() : 当显式中止方法调用之后,假如可被Closeable类或其他的对象没有被关闭。

##处罚


Penalty是英语“处罚”的意思,所以凡是以penalty开头的方法都表示违规时要做出什么反应。

对于每个策略,我们可以指定多个处罚形式,而处罚也是从最不严重的到最严重(从打印日志到直接crash(崩溃))依次执行。

暂时还没有机制能使监测到的违规与特定的处罚对应。

  • penaltyDeath() : 违规时,直接使应用崩溃。
  • penaltyDialog() : 违规时,向开发者显示一个恼人的Dialog对话框。
  • penaltyLog() : 违规时,将违规信息写入系统日志。

##使用


StrictMode使用起来非常简单。

###设置策略

你可以在你的Application(应用)或者应用中的Activity的onCreate()方法中设置启用StrictMode的策略。不过为了更全面的监测,最好就放在Application的onCreate()方法中,一劳永逸。

设置StrictMode可以通过setVmPolicy(StrictMode.VmPolicy)或setThreadPolicy(StrictMode.ThreadPolicy)。

setVmPolicy(StrictMode.VmPolicy)或setThreadPolicy(StrictMode.ThreadPolicy)方法的参数是用VmPolicy.Builder或ThreadPolicy.Builder来构建的。

举例:

@Override
public void onCreate() {super.onCreate();// 分别为MainThread和VM设置Strict Mode if (BuildConfig.DEBUG) {StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().detectResourceMismatches().detectCustomSlowCalls().penaltyDeath().build());StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().detectLeakedRegistrationObjects().detectActivityLeaks().penaltyDeath().build());}
}

###扩充StrictMode


1.用getThreadPolicy() 或getVmPolicy()获得当前策略。 2.用setThreadPolicy() or setVmPolicy()来扩充它。

举例:

StrictMode.ThreadPolicy oldThreadPolicy = StrictMode.getThreadPolicy();
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(oldThreadPolicy).permitDiskWrites()  // 在原有策略的规则基础上,不监测读写磁盘.build());StrictMode.VmPolicy oldVmPolicy = StrictMode.getVmPolicy();
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder(oldVmPolicy).detectFileUriExposure()   // 在原有策略的规则基础上,监测文件URI暴露.build());

###StrictMode的日志形式

09-04 16:15:34.592: DEBUG/StrictMode(15883): StrictMode policy violation; ~duration=319 ms: android.os.StrictMode$StrictModeDiskWriteViolation: policy=31 violation=1
09-04 16:15:34.592: DEBUG/StrictMode(15883):     at android.os.StrictMode$AndroidBlockGuardPolicy.onWriteToDisk(StrictMode.java:1041)

可以看到,在Logcat中总会有StrictMode开头的Log。因此,我们可以这样查找所有StrictMode的日志:

adb logcat | grep StrictMode

##测试实例


###写入外部存储

public void writeToExternalStorage() {File externalStorage = Environment.getExternalStorageDirectory();File destFile = new File(externalStorage, "dest.txt");try {OutputStream output = new FileOutputStream(destFile, true);output.write("coderunity.com".getBytes());output.flush();output.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}
}

###Activity泄露


下面的代码,如果我们进入、退出多次LeakyActivity, 则会触发 StrictMode.ThreadPolicy.Builder().detectActivityLeaks() :

public class MyApplication extends Application {public static final boolean IS_DEBUG = true;public static ArrayList<Activity> sLeakyActivities = new ArrayList<Activity>();
}public class LeakyActivity extends Activity{@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);MyApplication.sLeakyActivities.add(this);}
}

##在设置中启用StrictMode


我们也可以在Android设备的设置(Settings)中启用StrictMode:

Settings(设置) -> Developer options(开发者选项),然后开启它。开启之后,一旦应用在主线程中执行耗时操作,屏幕就会闪烁。

在开发者选项中开启StrictMode


人世间, 万千情感皆有温度, 千万代码似有性格。 这里有原创教程,IT丛林...... 和你一起探索程序人生。 我是谢恩铭,在巴黎奋斗的嵌入式软件工程师。 个人简介 热爱生活,喜欢游泳,略懂烹饪。 人生格言:“向着标杆直跑”

转载于:https://my.oschina.net/cxylm/blog/873072

这篇关于Android探索之旅 | StrictMode严苛模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/246082

相关文章

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级

Redis Cluster模式配置

《RedisCluster模式配置》:本文主要介绍RedisCluster模式配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录分片 一、分片的本质与核心价值二、分片实现方案对比 ‌三、分片算法详解1. ‌范围分片(顺序分片)‌2. ‌哈希分片3. ‌虚

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

RabbitMQ工作模式中的RPC通信模式详解

《RabbitMQ工作模式中的RPC通信模式详解》在RabbitMQ中,RPC模式通过消息队列实现远程调用功能,这篇文章给大家介绍RabbitMQ工作模式之RPC通信模式,感兴趣的朋友一起看看吧... 目录RPC通信模式概述工作流程代码案例引入依赖常量类编写客户端代码编写服务端代码RPC通信模式概述在R

SQL Server身份验证模式步骤和示例代码

《SQLServer身份验证模式步骤和示例代码》SQLServer是一个广泛使用的关系数据库管理系统,通常使用两种身份验证模式:Windows身份验证和SQLServer身份验证,本文将详细介绍身份... 目录身份验证方式的概念更改身份验证方式的步骤方法一:使用SQL Server Management S