Question

I have started using the Android StrictMode and find that it would be great to have it always running during development and not just on a special branch I created in git. The reason I did this is my apps requirement to run with 1.6 and up.

I read on the android developer blog that you can set it up so that you activate it via reflection. I was just wondering how that would actually look like and if it might be possible to have this documented here (or somewhere else) rather than having everybody that wants to use it work out themselves.

Was it helpful?

Solution 2

So I did not want to wait and decided to make the effort and implement this myself. It basically boils down to wrapping StrictMode in a wrapper class and deciding at runtime via reflection if we can activate it.

I have documented it in detail in a blog post and made it available in github.

OTHER TIPS

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);
    }

I saw your blog post. Since you only ever want to setup StrictMode at most once per Java file, would it make any sense to simplify the code to call for setup as follows?

Here's an alternate 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());
        }
    }
}

From your code, you only need to do the following:

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

where this is the local context, such as your Activity or Application or whatever. This seems to work for pre-2.3 Android, and also gives you the power of using the other methods of the Builder classes to configure StrictMode exactly as you'd like.

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.

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);

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);

}

Note: Disable the warning as you are already checking which version of the Android is going to use this code.

this Code will be activated if the Android version is higher than Android 2.2

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top