08 September, 2012

Stress Testing Android Application Activity Start/Stop

One of the things I find before delivering Android applications is the impact of starting and stopping the application in a rapid manner. It's common that key stroke and touch handlers get invoked before all the necessary resources have been created, or after they have been released. Starting an application, followed by hitting the back button or home button can often result in calls to your application handlers or scheduled behavior after onStop() has been invoked. I find the following script assists in stress testing this form of behavior:

#!/bin/bash


for t in {0..5}; do
  for i in {0..10}; do
    adb -s emulator-5554 shell am start -a android.intent.action.MYAPPNAME -n com.abc.myappname/com.abc.myappname.MyAppName
    sleep $t
    adb shell input keyevent 3
    sleep 5
  done
done

The above script will repeatedly start the application, wait X seconds, then post the 'home' keyevent. If my app passes this test, and a series of monkey tests I'm pretty confident the users won't experience unexpected crashes. Cheers.

06 September, 2012

Customizing Views with Android

My wife, a software engineer as well, pointed out today that I've been making customizing views more difficult than they have to be.  While I've been customizing views, buttons, and the like for some time I've felt that I needed to dynamically create the objects because I didn't think you could specify them in the XML layout.  Fortunately, I was incorrect.

Consider extending the ImageView class, demonstrated in the following example;


package com.abc.customview;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
import android.content.Context;
import android.util.AttributeSet;

class MyCanvasView extends ImageView {
        public MyCanvasView(Context context, AttributeSet attrs, int defStyle) {
                super(context, attrs, defStyle);
        }

        public MyCanvasView(Context context, AttributeSet attrs) {
                super(context, attrs);
        }

        public MyCanvasView(Context context) {
                super(context);
        }
};

public class CustomView extends Activity
{

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}
Normal XML layout would take the form;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Hello World, CustomView"
    />
  <ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:tint="#00000000"
    android:layout_gravity="center"
    android:src="@drawable/background"
    android:layout_weight="85"/>
</LinearLayout>
Using the extended class requires replacing the "ImageView" class specifier to our extended sub-class using full package namespace;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Hello World, CustomView"
    />
  <com.abc.customview.MyCanvasView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:tint="#00000000"
    android:layout_gravity="center"
    android:src="@drawable/background"
    android:layout_weight="85"/>
</LinearLayout>
Cheers.