12

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.

Manfred Moser
  • 28,342
  • 13
  • 87
  • 120
  • if I dont get an answer here I will figure it out myself when I have a bit of time to do it.. need to prep for andevcon at the moment though.. – Manfred Moser Jan 06 '11 at 02:21

6 Answers6

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);
    }
Manfred Moser
  • 28,342
  • 13
  • 87
  • 120
pixel
  • 21,352
  • 30
  • 113
  • 196
  • The implementation is in github and has been tested and used by many people. It works just fine. I use it every day. But yes... if you need target below 2.3 your trick will work as well. – Manfred Moser Nov 15 '11 at 17:47
  • @ManfredMoser The only reason I posted it is need to support targets lower than 2.3. Your solution is good, but in this special case it doesn't work. – pixel Nov 15 '11 at 20:06
8

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.

Manfred Moser
  • 28,342
  • 13
  • 87
  • 120
  • @bla ... kindly remove your downvote.. I fixed the link .. this is 5 years old. Things move around.. – Manfred Moser Mar 29 '16 at 22:38
  • Thanks Manfred; a downvote is generally an efficient way to get links fixed ;). One should check for MorseFlashApplication and StrictModeWrapper classes. – blacelle Mar 29 '16 at 22:54
7

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.

Dave MacLean
  • 5,094
  • 1
  • 20
  • 30
  • Yes.. that would work too and might be a bit shorter in the sense that it does not even try to use reflection but just does a full on init. It is a bit less flexible this way though. It is however true that you only want to do this all once. I just do it in the onCreate of the application class, which is a singleton already anyway.. – Manfred Moser Jan 18 '11 at 05:11
  • I once saw an answer from Dianne Hackborn on the Android Developers group that recommended against extending Application if it's not absolutely necessary. The policies apply to threads, so you could initialize StrictMode in the onCreate() of your launcher activity, and it should then be just as good as initializing from Application as it would apply to the main thread. Unless of course you fire up additional threads that you want to monitor, but you'd need to setup StrictMode on those threads as well even if you initialized from Application. – Dave MacLean Jan 18 '11 at 14:25
  • Yes. Thats another possibility. I also saw that recommendation from Dianne, but MANY apps I see extends application and it works quite well that way. Like they say .. there are many ways to skin a cat ;-) – Manfred Moser Jan 18 '11 at 23:49
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);
Unbroken
  • 21
  • 1
  • 5
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.

Andy Dennie
  • 5,872
  • 2
  • 27
  • 49
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);

}

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

Bill the Lizard
  • 369,957
  • 201
  • 546
  • 842
PravinDodia
  • 3,101
  • 1
  • 15
  • 22
  • This will not work on older Android versions since it assumes the class StrictMode is available.. which is not the case. – Manfred Moser Sep 04 '12 at 15:55
  • I am using this on my Android 2.2 with new application Popup Facebook, For this you have to choose target as stated above in the post there will be error in the logcat if the android version is lower than 2.3 but that would be about stating that there is a dead code. – PravinDodia Sep 09 '12 at 19:03
  • thats true but as far as the above code is concerned it should work theoretically, I have not tried for 1.1 but yes for sure it would work for Android 2.1 and above. – PravinDodia Sep 10 '12 at 19:28
  • @ManfredMoser I have not tried on Android 1.1 as i dont have the sdk for android 1.1 but yet i have tried on Android SDK 1.5. have you tired the code with 1.1? Please let me know if you have tried it so that i can edit my answer accordingly. – PravinDodia Sep 12 '12 at 00:21
  • It works for me below 2.3. The dalvik will log an error stating that he cannot find the class StrictMode but the app won't crash. It would only crash if we would try to use the StrictMode class and enter the IF branch - but we don't do that. Ergo, the snippet WORKS. – Zsolt Safrany Oct 25 '12 at 12:31