Mocking HTTP responses in Android using Robolectric

One of the nice features of Robolectric, is its ability to intercept HTTP requests and provide a way to return the HTTP responses you want. It is very useful, if you want to test code that reacts on certain HTTP requests. To accomplish this, Robolectric provides a fake HTTP layer, which you can configure with different complexity levels depending on your needs.

Mocking HTTP responses in Android using Robolectric weiterlesen

Android Unit Testing with Robolectric

The last weeks I had the chance to dive deeper into unit testing of an Android application. The solution we are using is Robolectric. It is an interesting and promising framework since it does not need an emulator but just runs as standard junit test. The tests we have been able to write and run with it are great. You can even create an instance of an activity, inflate the UI from layout files and check the state of single views. Or you can send a broadcast intent and check if it has been received.

Of course, Robolectric does not create a real UI for the tests. The way Robolectric allows testing of Android applications, works by intercepting the creation of instances of Android classes and provides some kind of proxy objects for them (so called Shadows). This way, the Robolectric developers have been able to rewrite parts of the platform’s behaviour, emulate the logic of a lot of classes and internally keep track of the state of the objects.

While this allows for efficient unit and integration testing without starting an emulator, it is clear that Robolectric tests do not replace testing on real Android devices or emulators with different OS versions. There are a few reasons for this:

  • The code just emulates the logic the Robolectric developers have implemented. For the most common use cases, this works well, but you find missing/limited functionality quite quickly. This will improve over time. Nevertheless, one has to be aware of the fact, that not the real Android classes are used and the behaviour can be different from the Robolectric classes.
  • The Robolectric framework does not emulate the real lifetime of an whole application. E.g. it will not start an activity or a service on its own. Also, it does not emulate the lifecycle of activities. This is by purpose, since it anyway is meant only for testing single units of the app. Of course, you can check which intent is being sent from an activity, which allows for testing the correct behaviour.
  • There are also general limits to this concept. E.g. when your app is not based on the standard View classes, but uses OpenGL, this can not be tested with Robolectric. I would say, all cases where real hardware is involved, can not be tested.

In summary, Robolectric allows efficient testing of a lot of use cases of an Android application. It is certainly not enough to make sure it will run on all devices. But it already provides a way to cover a lot of use cases of standard Android applications and make sure that the single components of your app behave correctly.

One thing that is heavily missing is better documentation, though. Without having the source code of Robolectric available and checking how it is implemented or looking at the unit tests of Robolectric itself, I would have not been able to figure out how some things are expected to work.
Therefore, I will try to collect here some howtos and hints for Robolectric in the coming weeks.


My other articles about Robolectric might also be interesting for you.

My summary of the Android Open Conference 2011

After arriving back in Germany from the O’Reilly Android Open Conference in San Francisco, I want to summarize my conclusions and general impressions.

Being in San Francisco and attending the conference was very inspiring. The keynotes have given a great overview what is possibly coming in the future and having Tim O’Reilly speaking about leveraging the openness of the Android platform was very motivating. As well as seeing what people are doing with standard hardware, like the NASA with Nexus S based mini satellites is crazy.

What was also great, was to „feel“ what makes the bay area so special in terms of innovations: ways are short, it is easy to connect with people from great companies ( be it startups or established ones), you get first class information from first hand, and people are very open to try out new things.

My summary of the Android Open Conference 2011 weiterlesen

SQLiteOpenHelper with Database on SD card

For certain reasons, e.g. because a database is very big, it might be necessary to put the database on the SD card instead of the internal storage of the phone. Of course, putting the database on the SD card should be carefully thought through because it adds quite a lot of complexity, e.g. by having to deal with the case that the SD card is unmounted or replaced.

Nevertheless, in cases this approach might be appropriate, it is not obvious how to configure the location of the database if you are using SQLiteOpenHelper. The solution is to overwrite the context’s openOrCreateDatabase method. This method is called by SQLiteOpenHelper when it needs to open the actual database.

E.g. you can use the following code to store the database in the applications private folder on the sdcard.

@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode,
CursorFactory factory) {
    File externalFilesDir = getExternalFilesDir(null);
    if(externalFilesDir == null) {
        return null;
    }

    File dbFile = new File(externalFilesDir, name);
    return SQLiteDatabase.openDatabase(dbFile.getAbsolutePath(), null, SQLiteDatabase.CREATE_IF_NECESSARY);
}

To overwrite this method, you can either inherit from ContextWrapper and then provide the wrapped context to the constructor of SQLiteOpenHelper or you can e.g. provide an own Application class with this overwritten method and then give the application context to the constructor of SQLiteHelper.

Great Android Memory Management Links

Here are some great links to get the basics of memory management for Android applications:

Java Performance blog: How to really measure the memory usage of your objects

Android Developers blog: Avoiding memory leaks

Java Performance blog: Eclipse Memory Analyzer, 10 useful tips/articles

Google IO 2011 Session: Memory management for Android Apps

Android: Displaying Modified Camera Preview Data

If you just want to have the camera preview data under Android without displaying the preview on the screen the problem is that you have to provide a surface to the Camera object for displaying the preview. On some devices it works without, but even the documentation states that you need to to set a preview surface for the camera to work.

Since I did not want to display the real data but only the processed data on the activity, I needed a solution for this problem. My first try was to include a hidden SurfaceView in the layout, but the SurfaceView does not create a surface if it is not visible. This post provided the first hint for solving the problem: You have to include a surface view and set the layout_height and layout_width parameters to „0dip“. This will trigger creation of the surface but the surfave view is virtually invisible.
Unfortunately, when trying this solution with different devices, it turned out that it does not work correctly  on all devices. On some devices the SurfaceView need to have visible size to make the camera preview work.

Finally, what worked on all devices is to overlay the SurfaceView completely with one or more other views so that it is logically visible but the user can not see it. In this way you can easily draw you own processed preview data in a custom view that is hiding the real preview.

Additionally important for further processing of the image data or if you want to display your own preview is that the camera data you get in your preview callback is normally not in RGB but YUV format. If you want to draw the image on a Canvas, you first have to convert the data to RGB, e.g. by using the method you can find described in this post of the Android Developer Forum.

(Interesting sidenote: the YUV format contains the grayscale image in the first width*heigth bytes, so if you just need a grayscale image, no conversion is needed).

Up from API level 8 there is also a YUVImage which you can use to convert the provided data to RGB, see stackoverflow for an example.

Android: Getting Path to Thumbnail

The standard way on Android to get a thumbnail is to use MediaStore.Images.Thumbnails.getThumbnail or MediaStore.Video.Thumbnails.getThumbnail dependent if you want a thumbnail from an image or an video. Both of these methods return a Bitmap ready to use.

However, sometimes you may want to have the path to the thumbnail, e.g. because your own ContentProvider also need to provide thumbnails for files. The documentation of the thumbnail functionality is not that clear currently, but to build this functionality you can query the standard thumbnail content provider similiar to querying the media store for the real file.

To get the path of a mini thumbnail (MINI_KIND) for the image on the external storage you could do the following:

String getThumbnailPathForLocalFile(long fileId)
{
    Cursor thumbCursor = null;
    try
    {
        thumbCursor = getContext().getContentResolver().
                query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI
                , null
                , MediaStore.Images.Thumbnails.IMAGE_ID + " = " + fileId+ " AND "
                  + MediaStore.Images.Thumbnails.KIND + " = "
                  + MediaStore.Images.Thumbnails.MINI_KIND , null, null);

        if(thumbCursor.moveToFirst())
        {
            // the path is stored in the DATA column
            int dataIndex = thumbCursor.getColumnIndexOrThrow( MediaStore.MediaColumns.DATA );
            String thumbnailPath = thumbCursor.getString(dataIndex);
            return thumbnailPath;
        }
    }
    finally
    {
        if(thumbCursor != null)
        {
            thumbCursor.close();
        }
    }

    return null;
}

Things to consider:

  • Querying the thumbnail content provider does not trigger the creation of the thumbnail. If the query does not return anything, you should trigger the creation of the thumbnail by calling the appropriate getThumbnail method and then querying the thumbnail content provider again.
  • Getting the path to the thumbnail only works for mini thumbnails (MINI_KIND) because only for these the Android system creates files to store the thumbnail. Micro thumbnails (MICRO_KIND) are stored in the database only. But at least you can get the raw data also by querying the thumbnail content provider as described above.

Interesting Google IO 2011 Sessions

Since I finally found the opportunity to have a look at some Google IO 2011 sessions, here are some links to sessions I can recommend:

Android Development Tools:
Shows some neat tips & tricks for using new (and old) features of the ADT plugin for Eclipse

Android Protips: Advanced Topics for Expert Android App Developers
Provides a lot of great tips and some patterns for common problems, e.g. keeping backward compatibility while still using new features, doing battery efficient data updates, etc.

Memory management for Android Apps
Background information about the garbage collector, memory management in the Dalvik VM and how to find memory problems by using the Eclipse Memory Analyzer

Building Aggressively Compatible Android Games
A good high-level summary of how to make apps compatible for many devices.