What is StrictMode in Android? – Part 1

SHARE & COMMENT :

StrictMode is a special class for verifying that your Android application is not doing things like disk I/O, Network access from the UI thread. This is a debugging feature introduced in Android 2.3. This developer tool detect things done accidentally and bring them to your attention so that you can fix them so as to avoid ANR dialogs(Activity Not Responding dialogs). StrictMode is used to setup thread and virtual machine policies for your application and report violations of such policies. You will get an alert if a policy is violated. You can instruct Android to crash your application with the alert or you can just log the alert and let your application carry on.

StrictMode Policies

Currently there are two types of policies available with StrictMode.

  • Thread Policy.
  • VM(Virtual Machine) policy.

ThreadPolicy of StrictMode

Thread policies are concerned with the non-recommended things that are done on the main application thread(UI thread), notably flash I/O and Network I/O.

Violations you can look for using ThreadPolicy are,

  • Disk reads
  • Disk writes
  • Network accesss
  • Slow calls

The possible alerts that you can choose are,

  • Write to LogCat
  • Display a dialog
  • Flash the screen
  • write to the DropBox log file
  • Crash the application

Setting up StrictMode’s ThreadPolicy

The below code tells you how to set up StrictMode for thread policies,

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskWrites()
.penaltyLog() //Logs a message to LogCat
.build());

A good place to set policies is at the entry points to your application and activities. For instance, in a simple application, you may need to just put the code in the onCreate() method of the launch Activity class. setThreadPolicy is a static method so you don’t need to actually instantiate a StrictMode object. setThreadPolicy() method internally uses current thread for policy. The method bulid() returns a ThreadPolicy object. In the above code snippet, the policy is defined to alert on disk writes by logging the messages to LogCat. There are various detect and penalty methods available for ThreadPolicy which are listed below.

The various detect methods for Thread Policy are,

detectDiskWrites() //API level 9
detectDiskReads() //API level 9
detectNetwork() //API level 9
detectCustomSlowCalls()//Introduced in API level 11

Instead of specific detect methods you can use detectAll() which detects all possible violations. detectCustomSlowCalls() is available from API level 11 using which you can detect slow code in your application.

The possible alerts(penalties) for thread policy are,

penaltyLog() //Logs a message to LogCat
penaltyDeath() //Crashes application, runs at the end of all enabled penalties
penaltyDialog() //Show a dialog
penaltyDeathOnNetwork() //Crashes the whole process on any network usage
penaltyDropBox() //Enable detected violations log a stacktrace and timing data to the DropBox on policy violation
penaltyFlashScreen() //Introduced in API level 11 which Flash the screen during a violation

The above is the list of penalty methods available for ThreadPolicy. You can use two or more penalties while setting up the ThreadPolicy which will be executed based on priority. For example, you can make your system to Log your messages via penaltyLog() before crashing the process via penaltyDeath(). If no penalties are enabled before calling build, penaltyLog() is implicitly set.

VmPolicy of StrictMode

VM policy deals with bad coding practices resulting memory leaks like Detect leaks of Activity subclasses. Detects when SQLite object is finalized without having been closed or if any Closeable object is finalized before it has been closed. It is created via the same builder class as shown below.

StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectActivityLeaks()
.detectLeakedClosableObjects()
.penaltyLog()
.build());

The possible policy violations for VmPolicy are,

detectActivityLeaks() //API level 11. Detect leaks of Activity subclasses.
detectLeakedClosableObjects() //API level 11. Detect when an Closeable or other object with a explict termination method is finalized without having been closed.
detectLeakedSqlLiteObjects() //API level 9. Detect when an SQLiteCursor or other SQLite object is finalized without having been closed.
setClassInstanceLimit(Class.forName("my.app.sample.sampleclass"),10) //API level 11

setClassInstanceLimit(className, Limit) is introduced in API level 11 which Sets an upper bound on how many instances of a class can be in memory at once. Helps to prevent object leaks.

The penalties that are applicable for VmPolicy Violations are,

penaltyLog()
penaltyDeath()
penaltyDropBox()

Note most of the Penalties that I have listed for ThreadPolicy are not application for VmPolicy. For example, you cannot be alerted by showing a dialog if a VmPolicy is violated.

If you find any problematic violations, you can solve them using various approaches like threads and handlers , AsyncTask  atc. Don’t try to solve all violations that your StrictMode detects. For example, Sometimes the disk I/O is necessary in your activities Lifecycle. In such cases you have to temporarily allow your Activity to access the DISK.  Android provides some helper methods to make it easier to allow disk reads and writes from the main thread temporarily. Such helper methods are,

  • allowThreadDiskReads()
  • allowThreadDiskWrites()

allowThreadDiskWrites() permits both disk reads & writes. Whereas allowThreadDiskReads() permits only disk read. Use the below code to allow disk access.

StrictMode.ThreadPolicy myoldpolicy=StrictMode.allowThreadDiskWrites();
//The code to write the DISK goes here
StrictMode.setThreadPolicy(myoldpolicy);

In the above code snippet,on line number 1 allowThreadDiskWrites() takes the current StrictMode.ThreadPolicy from getThreadPolic(), modifies it to permit both disk reads & writes, and sets the new policy with setThreadPolicy(StrictMode.ThreadPolicy), returning the old policy. Now “myoldpolicy” has the old StrictMode thread policy which is used to set the old policy again on line numer 3 after performing the nececcary Disk I/O. Note that There is no method for temporarily allowing network access.

So far we have learnt how to set up StrictMode for your application. Let us now study how to run your application with StrictMode. For that let us create a sample application, which has StrictMode enabled in it.

Step 1: Set up an Android working environment

If you are not familiar with setting up working environment for android, please follow the post Environment. For this example I would be using Android 4.0( API level 14).

Step 2: Create an Android Project

Create an android project named StrictModeTest with launcher activity StrictModeTestActivity. If you are not familiar with creating android projects, please follow one of our earlier posts Create a simple project.

Step 3: Create the required layouts

In this example, We would be using main.xml layout file. If you want to know more about layout files, please refer to the post Layouts in android. You need not to alter your main.xml file code for this example.

Step 4: Create required Activities

In this example, we would be using launcher activity StrictModeTestActivity.java. Open this and paste the below code,


package my.app;

import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;

public class StrictModeTestActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {

//setThreadPolicy is a static method
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskWrites()
.penaltyLog() //Logs a message to LogCat
.penaltyDialog() //Shows a dialog
.build());

//VmPolicy
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectActivityLeaks()
.detectLeakedClosableObjects()
.penaltyLog()
.build());

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

}
}

Now you are done with setting up StrictMode for DiskWrites. In the above example you are trying to read and write the file. Hence you would be alerted by LogCat messages and via dialogs.

Step 4: Run your application

Select your project-> right click-> Run As-> Android Application

Now the Activity fires up with the Dialog which alerts saying, you are violating the StrictMode policies.

StrictMode2

StrictMode is warning us that we are attempting  FILE write on application’s main thread. The same is being logged in LogCat since we have specified penaltyLog(). The LogCat stackTrace is as below.

02-14 19:08:57.419: D/StrictMode(30397): StrictMode policy violation; ~duration=29 ms: android.os.StrictMode$StrictModeDiskWriteViolation: policy=49 violation=1
02-14 19:08:57.419: D/StrictMode(30397):  at android.os.StrictMode$AndroidBlockGuardPolicy.onWriteToDisk(StrictMode.java:1048)
02-14 19:08:57.419: D/StrictMode(30397):  at libcore.io.BlockGuardOs.write(BlockGuardOs.java:178)
02-14 19:08:57.419: D/StrictMode(30397):  at libcore.io.IoBridge.write(IoBridge.java:447)
02-14 19:08:57.419: D/StrictMode(30397):  at java.io.FileOutputStream.write(FileOutputStream.java:187)
02-14 19:08:57.419: D/StrictMode(30397):  at java.io.OutputStreamWriter.flushBytes(OutputStreamWriter.java:167)
02-14 19:08:57.419: D/StrictMode(30397):  at java.io.OutputStreamWriter.close(OutputStreamWriter.java:140)
02-14 19:08:57.419: D/StrictMode(30397):  at java.io.BufferedWriter.close(BufferedWriter.java:98)
02-14 19:08:57.419: D/StrictMode(30397):  at my.app.StrictModeTestActivity.onCreate(StrictModeTestActivity.java:34)

You can observe the above LogCat messages, on Line number 1 it is saying the StrictMode policy is violated.

Note:  Do not use StrictMode in production code. It is designed for use when you are building,
testing, and debugging your application.

StrictMode was introduced in Android 2.3(API level 9) but more features were added in Android 3.0, so it is your duty to target the correct Android version and make sure your code is executed on the appropriate platforms. StrictMode is for android 2.3 and higher versions of android. Hence if in our application, the target API is 2.3 or higher and the MinSDK is below 9, this may crash your applications while testing on lower version emulator or devices.  We would be discussing how to support StrictMode in lower versions of android in our upcoming post StrictMode Part 2 . Stay Tuned. Hope this tutorial helped you to understand the usage of StrictMode. Please don’t forget to post your queries in comments section.

Comments

comments

About Krishna Srinivasan

He is Founder and Chief Editor of JavaBeat. He has more than 8+ years of experience on developing Web applications. He writes about Spring, DOJO, JSF, Hibernate and many other emerging technologies in this blog.

Speak Your Mind

*

Close
Please support the site
By clicking any of these buttons you help our site to get better