12

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

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

4

6 回答 6

9

I've read Manfred's blog post but it doesn't work if you set target platform version lower than 2.3 because StrictMode.enableDefaults(); method is unavailable.

Here is my solution that relies fully on reflection and doesn't generate compilation errors:

    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);
    }
于 2011-11-15T15:04:20.473 回答
8

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

在一篇博文中详细记录了它,并在github中提供了它。

于 2011-01-07T08:00:31.043 回答
7

我看到了你的博文。由于您只想在每个 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...");
}

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

于 2011-01-18T03:45:15.403 回答
1

I've thrown together another variation on the theme above, which I've outlined in a blog post here. The main difference in my approach is that it also provides wrappers for the disk and vm policy objects, so that you easily can bracket StrictMode-offending code with temporary policy changes. Feedback is welcome.

于 2011-09-26T18:31:47.553 回答
1

To Pixel code I also added this (based on StrictMode Android API example):

            // 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);
于 2012-07-31T20:35:42.717 回答
0

Set the Android Manifest to something like this.

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

use the below code in onCreate Method.

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,此代码将被激活

于 2012-09-04T14:55:31.337 回答