StrictMode:严格模式的使用

Quibbler 2021-6-5 943

StrictMode:严格模式的使用


        第一次接触使用StrictMode还是刚毕业的时候,现在再次记录一下StrictMode。本篇主要详细了解StrictMode的使用方法。关于StrictMode的实现原理详见另外一篇StrictMode原理剖析



1、StrictMode

        StrictMode是从Android 2.3(API 9)开始引入的调试工具。通常帮助开发者用来检测应用中出现的主线程I/O、主线程进行网络访问、内存泄漏等违规问题。

        切记,StrictMode必须只在debug版本启用,否则会对用户正常使用造成干扰。通常用BuildComfig.DEBUG条件判断。

    if (BuildConfig.DEBUG) {
        StrictMode.VmPolicy vmPolicy = new StrictMode.VmPolicy.Builder()
                .detectActivityLeaks()
                .detectCleartextNetwork()
                .detectFileUriExposure()
                .detectLeakedClosableObjects()
                .detectContentUriWithoutPermission()
                .build();
        StrictMode.setVmPolicy(vmPolicy);

        StrictMode.ThreadPolicy threadPolicy = new StrictMode.ThreadPolicy.Builder()
                .permitDiskReads()
                .detectDiskWrites()
                .detectNetwork()
                .detectCustomSlowCalls()
                .penaltyDialog()
                .build();
        StrictMode.setThreadPolicy(threadPolicy);
    }



2、StrictMode策略

        StrictMode中有两种策略:一个是线程策略,即ThreadPolicy,针对具体的线程;另一个是虚拟机策略,即VmPolicy,针对虚拟机中的所有对象。

        分别通过以下两个方法设置:

    //设置StrictMode虚拟机相关的策略
    StrictMode.setVmPolicy(vmPolicy)
    
    //设置StrictMode线程相关的策略
    StrictMode.setThreadPolicy(threadPolicy)

        VmPolicyThreadPolicy这两种策略都是StrictMode内部类,无法直接通过构造函数创建,两种策略内部都分别提供了Builder构造者创建各自示例。使用建造者模式的好处是开发者无需记住每种检测的flag,只需要通过构造者提供的方法去“定制”自己想要的策略。

        除了构造策略,还可以从StrictMode中拿出已有的策略修改使用:

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

        下面对StrictMode中的两种策略进行详细的介绍。


2.1、VmPolicy

        VmPolicy是虚拟机相关的策略。用来检测SQLiteCursor没关闭、实现Closable接口的类使用后没关闭等。通过内置的VmPolicy.Builder类构造VmPolicy实例:

    val vmPolicyBuilder: StrictMode.VmPolicy.Builder = StrictMode.VmPolicy.Builder()

        VmPolicy可以设置检测(detect)如下若干项:

    vmPolicyBuilder.apply {
        setClassInstanceLimit(Class klass, int instanceLimit)
        detectActivityLeaks()
        detectNonSdkApiUsage()
        detectLeakedSqlLiteObjects()
        detectLeakedClosableObjects()
        detectLeakedRegistrationObjects()
        detectFileUriExposure()
        detectCleartextNetwork()
        detectContentUriWithoutPermission()
        detectUntaggedSockets()
        detectImplicitDirectBoot()
        detectCredentialProtectedWhileLocked()
        //detectIncorrectContextUse()
        detectAll()
        ...
    }

        也可以设置允许(permit)某些违规:

    vmPolicyBuilder.apply {
        ...
        //permitActivityLeaks()
        permitNonSdkApiUsage()
        //permitUntaggedSockets()
        //permitImplicitDirectBoot()
        //permitCredentialProtectedWhileLocked()
        //permitIncorrectContextUse()
        ...
    }

        当发生违反VM策略的情况发生时,进行一些“惩罚”,有如下若干“penalty”项可选:输出log、弹框、“自杀”等等。

    vmPolicyBuilder.apply {
        ...
        penaltyDeath()
        penaltyDeathOnCleartextNetwork()
        penaltyDeathOnFileUriExposure()
        penaltyLog()
        penaltyDropBox()
        penaltyListener(Executor executor,OnVmViolationListener listener)
        penaltyListener(OnVmViolationListener listener,Executor executor)
    }

        最后,将构造好的VmPolicy实例设置给StrictMode

    val vmPolicy: StrictMode.VmPolicy = vmPolicyBuilder.build()
    StrictMode.setVmPolicy(vmPolicy)


2.2、ThreadPolicy

        ThreadPolicy是线程相关策略。可以检测出主线程访问网络、磁盘I/O、慢代码等违规操作。通过内置的ThreadPolicy.Builder类构造ThreadPolicy实例:

    val threadPolicyBuilder: StrictMode.ThreadPolicy.Builder = StrictMode.ThreadPolicy.Builder()

        设置下面的检测项,能够帮助开发者检测(detect)这些操作:    

    threadPolicyBuilder.apply {
        detectNetwork()
        detectDiskReads()
        detectDiskWrites()
        detectCustomSlowCalls()
        detectUnbufferedIo()
        detectResourceMismatches()
        //detectExplicitGc()
        detectAll()
        ...
    }

        还可以允许(permit)进行哪些操作:

    threadPolicyBuilder.apply {
        ...
        permitNetwork()
        permitDiskReads()
        permitDiskWrites()
        permitCustomSlowCalls()
        permitResourceMismatches()
        permitUnbufferedIo()
        //permitExplicitGc()
        permitAll()
        ...
    }

        一旦出现了违规(violation),可以设置惩罚(penalty),进行相应的提示,比如 Log、弹框等。

    threadPolicyBuilder.apply {
        ...
        //
        penaltyDialog()
        penaltyDeath()
        penaltyDeathOnNetwork()
        penaltyFlashScreen()
        penaltyLog()
        penaltyDropBox()
        penaltyListener(Executor executor,OnThreadViolationListener listener)
        penaltyListener(OnThreadViolationListener listener,Executor executor)
    }

        最后,将构造好的ThreadPolicy实例设置给StrictMode

    val threadPolicy = threadPolicyBuilder.build()
    StrictMode.setThreadPolicy(threadPolicy)



3、几种Penalty

        如何通过StrictMode检测出来?就是通过设置的penalty告知开发者发生违例操作,往往是借助Log、dropbox等定位问题。


3.1、弹框提醒

        设置了penaltyDialog(),当发生违反策略的情况发生时会弹框提醒开发者。不建议使用,很烦,因为可能会一直弹框,而且没有什么有用的信息。


3.2、打印Log

        设置了penaltyLog(),当发生违反策略的情况发生时输出D/StrictMode日志,包括详细的方法trace,可以定位到违例操作的代码处。



3.3、输出dropbox

        除了打印Log,当然可以将信息输出到dropbox文件中,保存关键信息。dropbox文件目录路径一般是/data/system/dropbox


        StrictMode使用就介绍到这里,用法很简单,因为框架在内部做了大量的“插桩”以便监控各种操作,接下来深入了解StrictMode的实现原理,详见StrictMode原理剖析



不忘初心的阿甘
最新回复 (0)
    • 安卓笔记本
      2
        登录 注册 QQ
返回
仅供学习交流,切勿用于商业用途。如有错误欢迎指出:fluent0418@gmail.com