【问题标题】:StrictMode for lower platform versions用于较低平台版本的 StrictMode
【发布时间】:2011-01-06 00:19:10
【问题描述】:

我已经开始使用 Android StrictMode,并发现让它在开发过程中始终运行而不只是在我在 git 中创建的特殊分支上运行会很棒。我这样做的原因是我的应用程序要求运行 1.6 及更高版本。

我在 android 开发者博客上读到,您可以设置它,以便通过反射激活它。我只是想知道这实际上会是什么样子,以及是否有可能在此处(或其他地方)记录此内容,而不是让每个想要使用它的人自己解决。

【问题讨论】:

  • 如果我在这里没有得到答案,我会在我有时间的时候自己解决。不过现在需要为 andevcon 做准备..

标签: android android-strictmode


【解决方案1】:

我已经阅读了 Manfred 的博文,但是如果您将 目标平台版本设置为低于 2.3 将不起作用,因为 StrictMode.enableDefaults(); 方法不可用。

这是我完全依赖反射并且不会产生编译错误的解决方案:

    try {
        Class<?> strictModeClass = Class.forName("android.os.StrictMode", true, Thread.currentThread()
                .getContextClassLoader());

        Class<?> threadPolicyClass = Class.forName("android.os.StrictMode$ThreadPolicy", true, Thread
                .currentThread().getContextClassLoader());

        Class<?> threadPolicyBuilderClass = Class.forName("android.os.StrictMode$ThreadPolicy$Builder", true,
                Thread.currentThread().getContextClassLoader());

        Method setThreadPolicyMethod = strictModeClass.getMethod("setThreadPolicy", threadPolicyClass);

        Method detectAllMethod = threadPolicyBuilderClass.getMethod("detectAll");
        Method penaltyMethod = threadPolicyBuilderClass.getMethod("penaltyLog");
        Method buildMethod = threadPolicyBuilderClass.getMethod("build");

        Constructor<?> threadPolicyBuilderConstructor = threadPolicyBuilderClass.getConstructor();
        Object threadPolicyBuilderObject = threadPolicyBuilderConstructor.newInstance();

        Object obj = detectAllMethod.invoke(threadPolicyBuilderObject);

        obj = penaltyMethod.invoke(obj);
        Object threadPolicyObject = buildMethod.invoke(obj);
        setThreadPolicyMethod.invoke(strictModeClass, threadPolicyObject);

    } catch (Exception ex) {
        Log.w(TAG, ex);
    }

【讨论】:

  • 实现在github中,已经被很多人测试和使用过。它工作得很好。我每天都使用它。但是是的......如果你需要低于 2.3 的目标,你的技巧也可以。
  • @ManfredMoser 我发布它的唯一原因是需要支持低于 2.3 的目标。您的解决方案很好,但在这种特殊情况下它不起作用。
【解决方案2】:

所以我不想等待,并决定自己努力并实施。它基本上归结为将 StrictMode 包装在一个包装类中,并在运行时通过反射决定我们是否可以激活它。

我已经详细记录了它in a blog post 并在github 中提供。

【讨论】:

  • @bla ...请删除您的反对票..我修复了链接..这是 5 岁。事情四处走动..
  • 谢谢曼弗雷德;否决票通常是固定链接的有效方法;)。应该检查 MorseFlashApplication 和 StrictModeWrapper 类。
【解决方案3】:

我看到了你的博文。由于您只希望每个 Java 文件最多设置一次 StrictMode,因此简化代码以调用 setup 如下所示是否有意义?

这是一个替代的 StrictModeWrapper:

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.StrictMode;

public class StrictModeWrapper {
    public static void init(Context context) {
        // check if android:debuggable is set to true
        int applicationFlags = context.getApplicationInfo().flags;
        if ((applicationFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectDiskReads()
                .detectDiskWrites()
                .detectNetwork()
                .penaltyLog()
                .build());
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectLeakedSqlLiteObjects()
                .penaltyLog()
                .penaltyDeath()
                .build());
        }
    }
}

从您的代码中,您只需执行以下操作:

try {
    StrictModeWrapper.init(this);
}
catch(Throwable throwable) {
    Log.v("StrictMode", "... is not available. Punting...");
}

其中 this 是本地上下文,例如您的 Activity 或 Application 或其他任何内容。这似乎适用于 2.3 之前的 Android,并且还使您能够使用 Builder 类的其他方法来完全按照您的意愿配置 StrictMode。

【讨论】:

  • 是的..这也可以,并且可能会更短一些,因为它甚至不尝试使用反射,而只是完整地初始化。不过这种方式不太灵活。但是,您确实只想这样做一次。我只是在应用程序类的 onCreate 中执行此操作,无论如何它已经是一个单例了..
  • 我曾经在 Android Developers group 上看到 Dianne Hackborn 的回答,如果不是绝对必要,建议不要扩展 Application。这些策略适用于线程,因此您可以在启动器活动的 onCreate() 中初始化 StrictMode,然后它应该与从应用程序初始化一样好,因为它将应用于主线程。当然,除非您启动了要监视的其他线程,但即使您从 Application 初始化,您也需要在这些线程上设置 StrictMode。
  • 是的。那是另一种可能。我也看到了 Dianne 的推荐,但我看到的许多应用程序都扩展了应用程序,而且这种方式效果很好。就像他们说的......有很多方法可以给猫剥皮;-)
【解决方案4】:

我在上面的主题上拼凑了另一个变体,我在一篇博文 here 中进行了概述。我的方法的主要区别在于它还为磁盘和虚拟机策略对象提供了包装器,因此您可以轻松地将违反 StrictMode 的代码包含在临时策略更改中。欢迎反馈。

【讨论】:

    【解决方案5】:

    对于像素代码,我还添加了这个(基于 StrictMode Android API 示例):

                // VM policy
                Class<?> VmPolicyClass = Class.forName("android.os.StrictMode$VmPolicy", true, Thread.currentThread().getContextClassLoader());
    
                Class<?> VmPolicyBuilderClass = Class.forName("android.os.StrictMode$VmPolicy$Builder", true, Thread.currentThread().getContextClassLoader());
    
                Method setVmPolicyMethod = strictModeClass.getMethod("setVmPolicy", VmPolicyClass);
    
                Method detectLeakedSqlLiteObjectsMethod = VmPolicyBuilderClass.getMethod("detectLeakedSqlLiteObjects");
                Method detectLeakedClosableObjectsMethod = null; 
                try
                {
                    detectLeakedClosableObjectsMethod = VmPolicyBuilderClass.getMethod("detectLeakedClosableObjects");
                }
                catch (Exception e) {}
                Method penaltyLogMethod = VmPolicyBuilderClass.getMethod("penaltyLog");
                Method penaltyDeathMethod = VmPolicyBuilderClass.getMethod("penaltyDeath");
                Method VmbuildMethod = VmPolicyBuilderClass.getMethod("build");
    
                Constructor<?> VmPolicyBuilderConstructor = VmPolicyBuilderClass.getConstructor();
                Object VmPolicyBuilderObject = VmPolicyBuilderConstructor.newInstance();
    
                Object Vmobj = detectLeakedSqlLiteObjectsMethod.invoke(VmPolicyBuilderObject);
                if (detectLeakedClosableObjectsMethod != null) Vmobj = detectLeakedClosableObjectsMethod.invoke(Vmobj);
                Vmobj = penaltyLogMethod.invoke(Vmobj);
                Vmobj = penaltyDeathMethod.invoke(Vmobj);
    
                Object VmPolicyObject = VmbuildMethod.invoke(Vmobj);
                setVmPolicyMethod.invoke(strictModeClass, VmPolicyObject);
    

    【讨论】:

      【解决方案6】:

      将 Android Manifest 设置为类似的内容。

      < uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" android:maxSdkVersion="16"/ >
      

      在 onCreate 方法中使用下面的代码。

      int SDK_INT = android.os.Build.VERSION.SDK_INT;
      
      } if (SDK_INT>8){
      
      StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
      
      StrictMode.setThreadPolicy(policy);
      
      }
      

      注意:禁用警告,因为您已经在检查哪个版本的 Android 将使用此代码。

      如果Android版本高于Android 2.2,此代码将被激活

      【讨论】:

      • 这不适用于较旧的 Android 版本,因为它假定类 StrictMode 可用。事实并非如此。
      • 我在我的 Android 2.2 上使用这个新应用程序 Popup Facebook,为此,您必须按照帖子中所述选择目标,如果 android 版本低于 2.3,logcat 中将出现错误但这就是说有一个死代码。
      • 没错,但就上述代码而言,理论上它应该可以工作,我没有尝试过 1.1,但可以肯定它适用于 Android 2.1 及更高版本。
      • @ManfredMoser 我没有在 Android 1.1 上尝试过,因为我没有 android 1.1 的 sdk,但我已经在 Android SDK 1.5 上尝试过。你厌倦了 1.1 的代码吗?如果您尝试过,请告诉我,以便我可以相应地编辑我的答案。
      • 它适用于我低于 2.3。 dalvik 将记录一个错误,指出他找不到类 StrictMode 但应用程序不会崩溃。如果我们尝试使用 StrictMode 类并进入 IF 分支,它只会崩溃——但我们不这样做。因此,sn-p 工作。
      猜你喜欢
      • 2016-09-29
      • 1970-01-01
      • 2018-10-19
      • 2019-12-17
      • 1970-01-01
      • 1970-01-01
      • 2021-05-02
      • 2021-02-25
      • 1970-01-01
      相关资源
      最近更新 更多