In our previous post StrictMode Part 1 we had discussed how to set up StrictMode in development environment and how to run your application with StrictMode enabled on emulator. In this tutorial we would be discussing more about dealing with StrictMode. The main topics that we are going to discuss are,
- Turning off StrictMode When your application goes to production
- StrictMode with older versions of Android(prior to Android 2.3)
- Buy: Hello, Android!!
Turning off StrictMode for Production purpose
I hope by now you have enough basic knowledge about what is StrictMode, how to enable it, and how to use it in production. Now we will discuss how to disable it when your application is ready to go on live failing which your application will crash on your users because of an alert. Below are the two ways by which you can disable StrictMode.
- Comment out or Remove the StrictMode code when your application finishes its building, testing and debugging stage.
- You can use production flags to skip the StrictMode setup code when it is not needed.
If you start commenting out the StrictMode code, it would be difficult for you to continue development if anything else is left out in development. Hence the second approach to turnoff the StrictMode during production is better to use. This is done by simply declaring any flag and assigning it a boolean variable “true” in debugging mode and making it false once you are done with the development. You can make use of android:debuggable attribute that is present in AndroidManifest.xml for <application> Tag. Developer no longer need to add the android:debuggable attribute to the <application> tag in the manifest. The build tools add the attribute automatically. When exporting a signed release build, the tools do not add the attribute in the manifest. So it is enough for you to check whether android:debuggable attribute is true or false while setting up StrictMode.
Use the below code to check for debug mode,
// collects information from <application> tag ApplicationInfo appInformation =context.getApplicationInfo(); //gives Flags associated with the application int appFlags = appInformation.flags; //Checks whether the application would like to allow debugging of its code if ((appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { // StrictMode setup goes here }
Above code checks for debug mode and performs the StrictMode set up accordingly.
StrictMode with older versions of Android(prior Android 2.3)
Lets assume we have an application targetting android 4.0(API 14) and minimum SDK version set to Android 2.2(API 8). I have made StrictMode enabled by using setThreadPolicy() and setVmPolicy() static methods. Now if you test your application on emulator of android 2.2(API 8), your application crashes by displaying ANR dialog. This is because StrictMode is not available in versions below Android 2.3. But your application works fine on Android 4.0 supporting emulators.
Lets see how can we get rid of this particular problem.
Create a separate method to deal with the older versions of Android( prior to Android 2.3) as below
try { //checks whether the strictMode class exists or what Class class_obj = Class.forName("android.os.StrictMode"); //if the StrictMode class exists, the control comes here Method enableDefaults = class_obj.getMethod("enableDefaults"); //dynamically invokes enableDefaults method which sets up StrictMode enableDefaults.invoke(null); } catch(Exception e) { // StrictMode not supported... Log.v("STRICTMODE", " Lower version of android, StrictMode not supported"); }
As you can see in the above code, first you are checking whether android.os.StrictMode class is available or not. If it’s not, a ClassNotFoundException occurs which is caught by the catch block and we are writing a LogCat message by using Log class. You shouldn’t get any exceptions if StrictMode does exist, because enableDefaults() is one of its methods.The enableDefaults() method sets up StrictMode to detect everything and to write any violations to LogCat. If you run your application with this set up, on emulator supporting versions below Android 2.3, you get an Message logged in Logcat by your catch block and if you run on emulators supporting Android 2.3 and above, you will be alerted when you perform non-recommended things.
Another approach to deal with older versions of Android is using StrictMode wrapper class. This enables you to work with Higher and lower versions of Android while using StrictMode. If StrictMode is not available for your application, an
Error will be thrown if you try to access it. If you wrap StrictMode in a class and then catch the error, you can ignore when StrictMode is not available and get it when it is.
Lets us change the sample example that we have developed in our earlier post StrictMode Part 1. Add a StrictMode wrapper class to the project StrictModeTest by creating a class named StrictModeWrapper.java in the package my.app . the code of the StrictModeWrapper.java is as below.
package my.app; import android.content.Context; import android.os.StrictMode; public class StrictModeWrapper { public static void enableStrictMode(Context context) { StrictMode.setThreadPolicy( new StrictMode.ThreadPolicy.Builder() .detectDiskReads() .detectDiskWrites() .detectNetwork() .penaltyLog() .build()); StrictMode.setVmPolicy( new StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects() .penaltyLog() .build()); } }
In the above code I have simply wrapped up the code of StrictMode set up that we have discussed in our earlier post, inside a enableStrictMode() static method.
Change the StrictModeTestActivity.java code to the below code.
package my.app; import java.io.BufferedWriter; import java.io.OutputStreamWriter; import android.app.Activity; import android.content.Context; import android.content.pm.ApplicationInfo; import android.os.Build; import android.os.Bundle; import android.util.Log; public class StrictModeTestActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { Context context=StrictModeTestActivity.this; //check whether debug mode is available int applicationflags = context.getApplicationInfo().flags; if ((applicationflags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { //check whether the Android version is >= 2.3.. if yes set up StrictMode by calling enableStrictMode() of wrapper class. if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.GINGERBREAD) { StrictModeWrapper.enableStrictMode(this); } else{ //If the android version is less than 2.3 log a message to LogCat Log.v("VERSION < Android 2.3", "StrictMode not supported"); } } super.onCreate(savedInstanceState); setContentView(R.layout.main); //Code to perform FILE I/O which will be caught by StrictMode try { OutputStreamWriter output_writer= new OutputStreamWriter(openFileOutput("FILETEST", MODE_WORLD_WRITEABLE)); BufferedWriter writer = new BufferedWriter(output_writer); writer.write("Hi This is my File to test StrictMode"); writer.close(); } catch (Exception e) { e.printStackTrace(); } } }
In the above code we are just checking whether the SDK version is Android 2.3 or higher. If yes we would be calling enableStrictMode() method of the wrapper class, which sets up StrictMode. If your version is lesser tha Android 2.3 you are logging a error message to the LogCat.
Run your application on emulator supporting Android 4.0, you would get the below LogCat message while your Program runs well.
02-15 16:25:04.665: D/StrictMode(929): StrictMode policy violation; ~duration=47 ms: android.os.StrictMode$StrictModeDiskWriteViolation: policy=49 violation=1 02-15 16:25:04.665: D/StrictMode(929): at android.os.StrictMode$AndroidBlockGuardPolicy.onWriteToDisk(StrictMode.java:1048) 02-15 16:25:04.665: D/StrictMode(929): at libcore.io.BlockGuardOs.write(BlockGuardOs.java:178) 02-15 16:25:04.665: D/StrictMode(929): at libcore.io.IoBridge.write(IoBridge.java:447) 02-15 16:25:04.665: D/StrictMode(929): at java.io.FileOutputStream.write(FileOutputStream.java:187) 02-15 16:25:04.665: D/StrictMode(929): at java.io.OutputStreamWriter.flushBytes(OutputStreamWriter.java:167) 02-15 16:25:04.665: D/StrictMode(929): at java.io.OutputStreamWriter.close(OutputStreamWriter.java:140) 02-15 16:25:04.665: D/StrictMode(929): at java.io.BufferedWriter.close(BufferedWriter.java:98) 02-15 16:25:04.665: D/StrictMode(929): at my.app.StrictModeTestActivity.onCreate(StrictModeTestActivity.java:35)
Now run your application on emulator supporting Android 2.3 and see the LogCat entries. A log is being entered in LogCat where as the program runs well.
02-15 18:16:21.905: V/VERSION < Android 2.3(386): StrictMode not supported
This is how you can make your code run on all versions of Android with StrictMode enabled. Hope this tutorial helped you to work with StrictMode. If you have any queries, please post it in comments section.
- Buy: Hello, Android!!