Running Instrumented Test in Android

An instrumented test is a fancy name for a test that runs within the Android device in the same process space as your app. This lets you test code that relies on Android SDK calls. The official guide is horridly incomplete. Here are a few quick notes.

Package Conflict

Android Studio builds a separate APK just for instrumented test. This runs in the same process space as the APK for the main app. Unfortunately this means both APKs must have no conflicting package dependencies. But the Internet is full of example of conflict with theĀ com.android.support:support-annotations package. You will need to force both APK to use a higher version.

androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'

//Force same version
androidTestCompile 'com.android.support:support-annotations:23.2.0'
compile 'com.android.support:support-annotations:23.2.0'

This is just an example only. By the time you read this newer versions may be available.

Location of the Test Java File

You have to create the test Java file in theĀ androidTest folder. This way it will get packaged with the test APK.

Annotation

An instrumented test class needs to have @RunWith and @SmallTest annotation.

A sample template class:

import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

@RunWith(AndroidJUnit4.class)
@SmallTest
public class InstrumentedTests {
 @Test
 public void testCaching() {
   assertNotNull("Hello");
   assertTrue(true);
   assertEquals("One", "One");
 }
}

Custom Theme in Android

Theming is useful when you need to apply a consistent custom look throughout the app. There are two ways you can do this in Android:

  1. Style: Define styles and then apply them to the widgets in layout XML. This can still be a lot of work since you have to apply the styles to each widget.
  2. Theme: Create a theme where you use the styles and then associate a theme at the application level. This will apply the styles throughout the app.

The way you define styles and theme depend on if your project is using the support library. Here I will describe the way things are done using the native SDK (not using support library).

Styles

You can define the styles in res/values/styles.xml. For example:

<resource>
    <style name="labelStyle">
        <item name="android:typeface">monospace</item>
        <item name="android:textColor">#00FF00</item>
    </style>
</resource>

Now, you can use the style with a widget in a layout XML.

<TextView android:text="@string/hello_world" 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    style="@style/labelStyle" />

You can override some of the style attribute at the individual widget level. For example, here we change the text color.

<TextView android:text="@string/hello_world" 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="#ff43cdff"
    style="@style/labelStyle" />

Theme

A theme applies styles at application level. This way you don’t have to set style for each widget.

You can define a theme in res/values/styles.xml. It’s strongly recommended that you derive your theme from a standard theme. That way you can just override what you need.

The theme below specifies the action bar background, title style and text view (label) style.

    <style name="AppTheme" parent="android:style/Theme.Holo.Light">
        <!-- Customize your theme here. -->
        <item name="android:actionBarStyle">@style/MyActionBar</item>
        <item name="android:windowBackground">@color/background</item>
        <item name="android:textViewStyle">@style/labelStyle</item>
    </style>

    <!-- ActionBar styles -->
    <style name="MyActionBar"
        parent="@android:style/Widget.Holo.Light.ActionBar.Solid.Inverse">
        <item name="android:background">#FF0000</item>
        <item name="android:titleTextStyle">@style/titleStyle</item>
    </style>
    <!-- ActionBar title styles -->
    <style name="titleStyle">
        <item name="android:fontFamily">sans-serif-condensed</item>
        <item name="android:textColor">#FFFFFF</item>
    </style>
    <!-- TextView styles -->
    <style name="labelStyle">
        <item name="android:typeface">monospace</item>
        <item name="android:textColor">#00FF00</item>
    </style>

    <color name="background">#cfcfcf</color>

Then, register your theme at the application level. Open AndroidManifest.xml and set the theme:

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

Individual widgets can override the theme by having their own style or directly setting properties like color and font.

Prevent Touch Event Theft in Android

In Android, touch events bubble up from child to parents as you would expect. However, a parent can choose to intercept all touch events targeted for one of its children and decide to veto dispatch of the event to the child. Widgets that scroll, like ListView or ExpandableListView, routinely do this to implement scrolling. But, this can lead to all kinds of nasty problems when you embed a child that needs touch gesture within such a parent. For example, adding a ViewPager within a ListView will cause the ViewPager to not work all that well.

Continue reading

Android Hardware Debugging from Ubuntu in VMWare

Some time back, I had posted an article on Android hardware debugging from Windows. The process is much simpler in Mac OS X or Ubuntu Linux. There, you don’t need to install any special device drivers. Today, I managed to connect my HTC Thunderbolt to Ubuntu 12.04 running as a VMWare guest. The process was simple and worked the first time. Here are the basic steps. I use VMWare Player. I assume the steps will be almost the same for VMWare Workstation.

These steps assume that you have a basic Ubuntu workstation working as a VMWare guest. Log into Ubuntu as the administrator user and then carry out these steps.

Step 1 – Install JDK and Android SDK

You will need Oracle JDK installed. Just download the distribution and unzip it somewhere. Then add <JDK>/bin folder to your PATH. If you are not sure, follow this guide.

Go to http://developer.android.com/sdk/ and download the SDK for Linux. Extract it somewhere, say within your Documents folder. In my case, this created the ~/Documents/android-sdk-linux folder. I will refer to this folder as <SDK> from now on.

Step 2 – Download SDK Platforms

From a command prompt, go to <SDK>/tools. Run this command to open the SDK manager.

./android sdk

Download the version of Android platform that is right for your phone. For example, my phone is running Android 2.3.4. So, I downloaded the nearest Android SDK 2.3.3.

For more information on downloading SDK platforms, read Google’s official guide.

Step 3 – Configure udev

udev is the Linux dynamic device management software. We will need to register our phone as a USB device.

From the command prompt, go to /etc/udev/rules.d folder.

Create a file in that folder called 51-android.rules as follows.

sudo vi 51-android.rules

In that file, I entered a single line for my HTC Thunderbolt.

SUBSYSTEM=="usb", ATTR{idVendor}=="0bb4", MODE="0666", GROUP="mygroup"

In your case, you will need to enter a different vendor ID (0bb4 is for HTC) and UNIX group that will own the device. For a list of vendor IDs and more information read the official hardware debugging guide.

Then, give read permission to the file for everyone.

sudo chmod a+r 51-android.rules

Step 4 – Plug in the Phone

Before you plugin your phone, enable USB debugging (Settings > Application > Development > USB Debugging).

While the VMWare guest window is in the foreground, plug in the phone to a USB slot. VMWare should automatically connect the guest with the device. Note: a device can be connected to either a guest or the host but not both. The fact that VMWare connected the device to the guest by default saved me a lot of trouble.

Step 5 – Test Connection

From the command prompt, go to <SDK>/platform-tools. Then run this command:

adb devices

Make sure that your phone is listed.