Building and running native Android apps on Windows

There are a number of well-documented approaches to developing native Android apps but many are not devoted to developing from the Windows command line but instead focus on using IDEs such as Eclipse. This article covers getting going quickly on the command line using just the Android developer tools and no IDEs.

The high level steps are as follows:

  • Install the prerequisites
  • Find and build a sample’s native components
  • Package the sample as an Android app
  • Deploy the sample to a device

After I go over doing this “the hard way” I’ll introduce you to using the Fun Propulsion Labs native app utilities for simplifying the build process. Let’s get going!

Prerequisites

You will need the following components:

  1. The Android Native Development Kit (NDK) – Provides compiler tools and sample code
  2. Apache Ant – Works with the Android build tools to create Android APKs
  3. The Java Development Kit JDK

You must correctly configure the components. This means opening up your environment variables and adding a user variable, JAVA_HOME, that points to the root folder of the JDK. For compatibility, you should use a Windows-abridged style path, e.g.:

C:Progra~1Javajdk1.7.0_21

Because Ant may not work with newer style paths on Windows.

Build a sample

Navigate to the folder you want to build from e.g. samplesnative-plasma. After navigating to the folder, build using the NDK. For example:

....ndk_build

When you invoke the command, you will get output indicating the build was successful.

[arm64-v8a] Gdbserver      : [aarch64-linux-android-4.9] libs/arm64-v8a/gdbserver
[arm64-v8a] Gdbsetup       : libs/arm64-v8a/gdb.setup
[x86_64] Gdbserver      : [x86_64-4.9] libs/x86_64/gdbserver
[x86_64] Gdbsetup       : libs/x86_64/gdb.setup
[mips64] Gdbserver      : [mips64el-linux-android-4.9] libs/mips64/gdbserver
[mips64] Gdbsetup       : libs/mips64/gdb.setup
[armeabi-v7a] Gdbserver      : [arm-linux-androideabi-4.6] libs/armeabi-v7a/gdbserver
[armeabi-v7a] Gdbsetup       : libs/armeabi-v7a/gdb.setup
[armeabi] Gdbserver      : [arm-linux-androideabi-4.6] libs/armeabi/gdbserver
[armeabi] Gdbsetup       : libs/armeabi/gdb.setup
[x86] Gdbserver      : [x86-4.6] libs/x86/gdbserver
[x86] Gdbsetup       : libs/x86/gdb.setup
[mips] Gdbserver      : [mipsel-linux-android-4.6] libs/mips/gdbserver
[mips] Gdbsetup       : libs/mips/gdb.setup
[arm64-v8a] Compile        : native-plasma <= plasma.c
[arm64-v8a] Compile        : android_native_app_glue <= android_native_app_glue.c
[arm64-v8a] StaticLibrary  : libandroid_native_app_glue.a
[arm64-v8a] SharedLibrary  : libnative-plasma.so
[arm64-v8a] Install        : libnative-plasma.so => libs/arm64-v8a/libnative-plasma.so
[x86_64] Compile        : native-plasma <= plasma.c
[x86_64] Compile        : android_native_app_glue <= android_native_app_glue.c
[x86_64] StaticLibrary  : libandroid_native_app_glue.a
[x86_64] SharedLibrary  : libnative-plasma.so
[x86_64] Install        : libnative-plasma.so => libs/x86_64/libnative-plasma.so
[mips64] Compile        : native-plasma <= plasma.c
[mips64] Compile        : android_native_app_glue <= android_native_app_glue.c
[mips64] StaticLibrary  : libandroid_native_app_glue.a
[mips64] SharedLibrary  : libnative-plasma.so
[mips64] Install        : libnative-plasma.so => libs/mips64/libnative-plasma.so
[armeabi-v7a] Compile thumb  : native-plasma <= plasma.c
[armeabi-v7a] Compile thumb  : android_native_app_glue <= android_native_app_glue.c
[armeabi-v7a] StaticLibrary  : libandroid_native_app_glue.a
[armeabi-v7a] SharedLibrary  : libnative-plasma.so
[armeabi-v7a] Install        : libnative-plasma.so => libs/armeabi-v7a/libnative-plasma.so
[armeabi] Compile thumb  : native-plasma <= plasma.c
[armeabi] Compile thumb  : android_native_app_glue <= android_native_app_glue.c
[armeabi] StaticLibrary  : libandroid_native_app_glue.a
[armeabi] SharedLibrary  : libnative-plasma.so
[armeabi] Install        : libnative-plasma.so => libs/armeabi/libnative-plasma.so
[x86] Compile        : native-plasma <= plasma.c
[x86] Compile        : android_native_app_glue <= android_native_app_glue.c
[x86] StaticLibrary  : libandroid_native_app_glue.a
[x86] SharedLibrary  : libnative-plasma.so
[x86] Install        : libnative-plasma.so => libs/x86/libnative-plasma.so
[mips] Compile        : native-plasma <= plasma.c
[mips] Compile        : android_native_app_glue <= android_native_app_glue.c
[mips] StaticLibrary  : libandroid_native_app_glue.a
[mips] SharedLibrary  : libnative-plasma.so
[mips] Install        : libnative-plasma.so => libs/mips/libnative-plasma.so

Next, create the android project using the Android build tools. For example:

android update project --path . --name native-plasma --target 20

This will generate the Android project files, such as build.xml. Finally, you can build the APK using Ant. For example:

ant debug

Will generate the debug package for the application in the current folder.

Deploy and run the app

Now that you have built the APK, you are ready to install it to your Android device. The following command uses the Android developer tools again to install the app:

adb install binnative-plasma.apk

With the app deployed to your device, you can now run it! The following image shows the native-plasma app running on my MotoX.

Screenshot_2014-11-11-08-26-32

Congratulations, you’ve built and installed a purely native Android app!

Building using the Fun Propulsion Labs utilities

The Fun Propulsion Labs (FPL) team has made a collection of utilities for native developers. These tools simplify the native development process, enable build automation, and also provide performance insights into your code. For the FPL utilities, you must first install Python. After installation finishes, add Python to your path (it was in c:python27 for me).

With Python on your system path, it’s time to clone the FPL git repository.

git clone https://github.com/google/fplutil

Now, you can try building one of the example projects. I started with the buildutil_example/android. From this folder call:

build.py -n c:usersGusandroid-ndk-r10c

This will kick off the build and will compile the native-plasma project. After building, you can install the APK from the project sources folder just as you did before:

adb install native-plasma/bin/native-plasma-debug.apk

Building with the FPL utilities is much cleaner!

Note If you’re using Cygwin, you must modify the folder containing the Windows Android Tools to have an alias from the Android.bat file to just android:

pushd /cygdrive/c/Users/Gus/android-sdks/tools

ln -s android.bat android

Then you would run:

./build.py -n ~/android-ndk-r10c/ -s ~/android-sdks/

from the Cygwin command line … The build can fail, with OSError: [Errno 11]. If this happens, just retry once or twice and the build will get past this issue.

Running Built Samples on the new Visual Studio 2015 Plugin

There was a recent announcement from Microsoft that the next version of Visual Studio will support Android. So, naturally, I tried it out. The sample structure that is used in the Visual Studio template doesn’t use Java and is built around Native Activity so I couldn’t easily port any of the existing samples. However, the emulator worked great!

To run in the emulator:

  • Install Visual Studio 2015 Preview, be sure to install the Android Simulator
  • Start the emulator from Visual Studio
  • From here, you can just drag and drop your apk to the emulator

Using ADB with the emulator

  • Determine the device IP address by opening up the network tab of the emulator settings. In the following example, it’s 192.168.1.134
  • network
  • Connect over TCP to the emulator:
    adb connect 192.168.1.134
  • Run your install  command (I was using cygwin paths, if you use cmd.exe these are backslashes):
    adb install ~/fplutil/examples/buildutil_example/android/native-plasma/bin/native-plasma-debug.apk
  • The app will install on the device and can be launched
    native_plasma

 

Conclusions

Building native Android apps isn’t too bad. When you’re developing native apps, the FPL utilities can save you a number of steps and make it easier. Because the tools are new, I haven’t had enough time to fully explore what they are capable of but for starters, being able to create Android apps using the more conventional pattern from C/C++ of beginning execution in main() is interesting! I’ll look deeper into the library in a future article. For now, you can discuss fplutil with other developers and users on the fplutil Google Group. File issues on the fplutil Issues Tracker or post your questions to stackoverflow.com with a mention of fplutil.

In celebration of getting native apps, building, I produced an accurate Androidified version of me doing the happy dance:

android

Until next time!