Wednesday, October 9, 2013

How to add unit tests to Android Studio project

Modify the build.gradle file

First of all remeber to modify the module's build.gradle file and not the one in the project.
In the android, defaultConfig section add this

testPackage "<package>.test"
testInstrumentationRunner "android.test.InstrumentationTestRunner"

In the dependencies section add this

instrumentTestCompile 'junit:junit:3.8'

Save the file and click the Sync Project with Gradle Files button.

Add unit tests

Under <Project>, <Module>, src add a folder named instrumentTest. Under this create a folder named java and here create a new package named <package>.test.

Now create a class named <ClassName>Test that inherits from android.test.InstrumentationTestCase. In this class individual tests of the class <ClassName> can be written, e.g.

public void testSomeMethodInClass() throws Exception {
    final int expected = 1;
    final int actual = Class.Method();
    assertEquals(expected, actual);
}

Execute test

Right-click on the test method, e.g. testSomeMethodInClass in the example above, choose Run and testSomeMethodInClass. Take the one with the Android icon!

Now a dialog to choose device or emulator will most likely appear. Choose which one to run the test on.

Project structure

<Project>
+-.idea
+-gradle
+-<Module>
| +-build
| +-src
| | +-instrumentTest
| | | +-java
| | |   +-<package>.test
| | |     +-<ClassName>Test
| | +-main
| |   +-java
| |   | +-<package>
| |   |   +-<ClassName>
| |   +-res
| |   | +-drawable...
| |   | + ...
| |   | +-values...
| |   +-AndroidManifest.xml
| +-build.gradle  <<------------ THIS ONE!
+-build.gradle  <<-------------- *NOT* THIS ONE!


Sunday, June 2, 2013

Make the Google+ SDK Sample app work

I was following the Google+ quick start guide for Android to the letter and found the last step quite frustrating:

Select Run > Run to test the PlusSampleActivity sample app. Choose Android application if prompted. The sample application will launch on your device.
When I launched the app from Eclipse I kept getting a crash. My LogCat looked like this:

I/dalvikvm(9444): Failed resolving Lcom/google/android/gms/samples/plus/PlusOneActivity; interface 556 'Lcom/google/android/gms/common/GooglePlayServicesClient$ConnectionCallbacks;'W/dalvikvm(9444): Link of class 'Lcom/google/android/gms/samples/plus/PlusOneActivity;' failed E/dalvikvm(9444): Could not find class 'com.google.android.gms.samples.plus.PlusOneActivity', referenced from method com.google.android.gms.samples.plus.PlusSampleActivity.<clinit>
W/dalvikvm(9444): VFY: unable to resolve const-class 590 (Lcom/google/android/gms/samples/plus/PlusOneActivity;) in Lcom/google/android/gms/samples/plus/PlusSampleActivity;
D/dalvikvm(9444): VFY: replacing opcode 0x1c at 0x0018
W/dalvikvm(9444): Exception Ljava/lang/NoClassDefFoundError; thrown while initializing Lcom/google/android/gms/samples/plus/PlusSampleActivity;
W/dalvikvm(9444): Class init failed in newInstance call (Lcom/google/android/gms/samples/plus/PlusSampleActivity;)

D/AndroidRuntime(9444): Shutting down VM
W/dalvikvm(9444): threadid=1: thread exiting with uncaught exception (group=0x4203e2a0)
E/AndroidRuntime(9444): FATAL EXCEPTION: main
E/AndroidRuntime(9444): java.lang.ExceptionInInitializerErrorE/AndroidRuntime(9444): at java.lang.Class.newInstanceImpl(Native Method)
E/AndroidRuntime(9444): at java.lang.Class.newInstance(Class.java:1319)
E/AndroidRuntime(9444): at android.app.Instrumentation.newActivity(Instrumentation.java:1068)
E/AndroidRuntime(9444): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2025)
E/AndroidRuntime(9444): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135)
E/AndroidRuntime(9444): at android.app.ActivityThread.access$700(ActivityThread.java:140)
E/AndroidRuntime(9444): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
E/AndroidRuntime(9444): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(9444): at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(9444): at android.app.ActivityThread.main(ActivityThread.java:4921)
E/AndroidRuntime(9444): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(9444): at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(9444): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
E/AndroidRuntime(9444): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
E/AndroidRuntime(9444): at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(9444): Caused by: java.lang.NoClassDefFoundError: com.google.android.gms.samples.plus.PlusOneActivity
E/AndroidRuntime(9444): at com.google.android.gms.samples.plus.PlusSampleActivity.<clinit>(PlusSampleActivity.java:46)
E/AndroidRuntime(9444): ... 15 more

I/Process(9444): Sending signal. PID: 9444 SIG: 9

After some googling around I stumbled upon this solution on StackOverflow: http://stackoverflow.com/questions/2247998/noclassdeffounderror-eclipse-and-android/9916751#9916751

It pretty much explains that the way external libraries has to be included in an Eclipse project have changed. The Google Play Services library was included in the project properties under Android > Library.
Reference: ..\..\libproject\google-play-services_lib
Project: google-play-services_lib
Remove this reference and instead add it in the project properties under Java Build Path > Libraries tab. Click "Add External JARs..." and browse to <android-sdk-folder>\extras\google\google_play_services\libproject\google-play-services_lib\libs. Select "google-play-services.jar". Now go to the Order and Export tab and select "google-play-services.jar".

Now the Google+ SDK Sample app runs and works!

Monday, January 21, 2013

How to check if a WaitHandle is set

Say you have a wait handle of type EventWaitHandle and want to check if it is set or not. To do this call the WaitOne(int) method with a timeout of zero. It will return true if the wait handle is set and false otherwise.

Example


using System;
using System.Threading;
 
namespace ConsoleApp {
    public class Program {
        /// <summary>
        /// Running this program will output
        ///     Wait handle is not set
        ///     Wait handle is set
        /// to the console.
        /// </summary>
        public static void Main(string[] args) {
            var waitHandle = new EventWaitHandle(falseEventResetMode.ManualReset);
 
            Console.WriteLine(waitHandle.WaitOne(0) ? "Wait handle is set" : "Wait handle is not set");
 
            waitHandle.Set();
 
            Console.WriteLine(waitHandle.WaitOne(0) ? "Wait handle is set" : "Wait handle is not set");
        }
    }
}