Home Mobile Tutorials Creating, Compiling, and Deploying Native Projects from the Android NDK

Creating, Compiling, and Deploying Native Projects from the Android NDK

0
4599
13 min read

(For more resources on Android, see here.)

Compiling and deploying NDK sample applications

I guess you cannot wait anymore to test your new development environment. So why not compile and deploy elementary samples provided by the Android NDK first to see it in action? To get started, I propose to run HelloJni, a sample application which retrieves a character string defined inside a native C library into a Java activity (an activity in Android being more or less equivalent to an application screen).

Time for action – compiling and deploying hellojni sample

Learn Programming & Development with a Packt Subscription

Let’s compile and deploy HelloJni project from command line using Ant:

  1. Open a command-line prompt (or Cygwin prompt on Windows).
  2. Go to hello-jni sample directory inside the Android NDK. All the following steps have to performed from this directory:

    $ cd $ANDROID_NDK/samples/hello-jni

  3. Create Ant build file and all related configuration files automatically using android command (android.bat on Windows). These files describe how to compile and package an Android application:

    android update project –p .

  4. (Move the mouse over the image to enlarge.)

  5. Build libhello-jni native library with ndk-build, which is a wrapper Bash script around Make. Command ndk-build sets up the compilation toolchain for native C/ C++ code and calls automatically GCC version featured with the NDK.

    $ ndk-build

  6. Make sure your Android development device or emulator is connected and running.
  7. Compile, package, and install the final HelloJni APK (an Android application package). All these steps can be performed in one command, thanks to Ant build automation tool. Among other things, Ant runs javac to compile Java code, AAPT to package the application with its resources, and finally ADB to deploy it on the development device. Following is only a partial extract of the output:

    $ ant install

  8. The result should look like the following extract:

  9. Launch a shell session using adb (or adb.exe on Windows). ADB shell is similar to shells that can be found on the Linux systems:

    $ adb shell

  10. From this shell, launch HelloJni application on your device or emulator. To do so, use am, the Android Activity Manager. Command am allows to start Android activities, services or sending intents (that is, inter-activity messages) from command line. Command parameters come from the Android manifest:

    # am start -a android.intent.action.MAIN -n com.example.hellojni/com.example.hellojni.HelloJni

  11. Finally, look at your development device. HelloJni appears on the screen!

What just happened?

We have compiled, packaged, and deployed an official NDK sample application with Ant and SDK command-line tools. We will explore them more in later part. We have also compiled our first native C library (also called module) using the ndk-build command. This library simply returns a character string to the Java part of the application on request. Both sides of the application, the native and the Java one, communicate through Java Native Interface. JNI is a standard framework that allows Java code to explicitly call native C/C++ code with a dedicated API.

Finally, we have launched HelloJni on our device from an Android shell (adb shell) with the am Activity Manager command. Command parameters passed in step 8 come from the Android manifest: com.example.hellojni is the package name and com.example.hellojni. HelloJni is the main Activity class name concatenated to the main package.

<?xml version="1.0" encoding="utf-8"?>
<manifest
package="com.example.hellojni" HIGHLIGHT
android_versionCode="1"
android_versionName="1.0">
...
<activity android_name=".HelloJni" HIGHLIGHT
android_label="@string/app_name">
...

Automated build
Because Android SDK, NDK, and their open source bricks are not bound to Eclipse or any specific IDE, creating an automated build chain or setting up a continuous integration server becomes possible. A simple bash script with Ant is enough to make it work!

HelloJni sample is a little bit… let’s say rustic! So what about trying something fancier? Android NDK provides a sample named San Angeles. San Angeles is a coding demo created in 2004 for the Assembly 2004 competition. It has been later ported to OpenGL ES and reused as a sample demonstration in several languages and systems, including Android. You can find more information by visiting one of the author’s page: http://jet.ro/visuals/4k-intros/san-angeles-observation/.

Have a go hero – compiling san angeles OpenGL demo

To test this demo, you need to follow the same steps:

  1. Go to the San Angeles sample directory.
  2. Generate project files.
  3. Compile and install the final San Angeles application.
  4. Finally run it.

As this application uses OpenGL ES 1, AVD emulation will work, but may be somewhat slow!

You may encounter some errors while compiling the application with Ant:

The reason is simple: in res/layout/ directory, main.xml file is defined. This file usually defines the main screen layout in Java application—displayed components and how they are organized. However, when Android 2.2 (API Level 8) was released, the layout_width and layout_height enumerations, which describe the way UI components should be sized, were modified: FILL_PARENT became MATCH_PARENT. But San Angeles uses API Level 4.

There are basically two ways to overcome this problem. The first one is selecting the right Android version as the target. To do so, specify the target when creating Ant project files:

$ android update project –p . -–target android-8

This way, build target is set to API Level 8 and MATCH_PARENT is recognized. You can also change the build target manually by editing default.properties at the project root and replacing:

target=android-4

with the following line:

target=android-8

The second way is more straightforward: erase the main.xml file! Indeed, this file is in fact not used by San Angeles demo, as only an OpenGL screen created programmatically is displayed, without any UI components.

Target right!
When compiling an Android application, always check carefully if you are using the right target platform, as some features are added or updated between Android versions. A target can also dramatically change your audience wideness because of the multiple versions of Android in the wild… Indeed, targets are moving a lot and fast on Android!.

All these efforts are not in vain: it is just a pleasure to see this old-school 3D environment full of flat-shaded polygons running for the first time. So just stop reading and run it!

Exploring android SDK tools

Android SDK includes tools which are quite useful for developers and integrators. We have already overlooked some of them including the Android Debug Bridge and android command. Let’s explore them deeper.

 

Android debug bridge

You may have not noticed it specifically since the beginning but it has always been there, over your shoulder. The Android Debug Bridge is a multifaceted tool used as an intermediary between development environment and emulators/devices. More specifically, ADB is:

  • A background process running on emulators and devices to receive orders or requests from an external computer.
  • A background server on your development computer communicating with connected devices and emulators. When listing devices, ADB server is involved. When debugging, ADB server is involved. When any communication with a device happens, ADB server is involved!
  • A client running on your development computer and communicating with devices through ADB server. That is what we have done to launch HelloJni: we got connected to our device using adb shell before issuing the required commands.

ADB shell is a real Linux shell embedded in ADB client. Although not all standard commands are available, classical commands, such as ls, cd, pwd, cat, chmod, ps, and so on are executable. A few specific commands are also provided such as:

logcat

To display device log messages

dumpsys

To dump system state

dmesg

To dump kernel messages

ADB shell is a real Swiss Army knife. It also allows manipulating your device in a flexible way, especially with root access. For example, it becomes possible to observe applications deployed in their “sandbox” (see directory /data/data) or to a list and kill currently running processes.

ADB also offers other interesting options; some of them are as follows:

pull <device path> <local path>

To transfer a file to your computer

push <local path> <device path>

To transfer a file to your device or emulator

install <application package>

To install an application package

install -r <package to reinstall>

To reinstall an application, if already deployed

devices

To list all Android devices currently connected, including emulators

reboot

To restart an Android device programmatically

wait-for-device

To sleep, until a device or emulator is connected to your computer (for example,. in a script)

start-server

To launch the ADB server communicating with devices and emulators

kill-server

To terminate the ADB server

bugreport

To print the whole device state (like dumpsys)

help

To get an exhaustive help with all options and flags available

To ease the writing of issued command, ADB provides facultative flags to specify before options:

-s <device id>

To target a specific device

-d

To target current physical device, if only one is connected (or an error message is raised)

-e

To target currently running emulator, if only one is connected (or an error message is raised)

ADB client and its shell can be used for advanced manipulation on the system, but most of the time, it will not be necessary. ADB itself is generally used transparently. In addition, without root access to your phone, possible actions are limited. For more information, see http://developer.android.com/guide/developing/tools/adb.html.

Root or not root.
If you know the Android ecosystem a bit, you may have heard about rooted phones and non-rooted phones. Rooting a phone means getting root access to it, either “officially” while using development phones or using hacks with an end user phone. The main interest is to upgrade your system before the manufacturer provides updates (if any!) or to use a custom version (optimized or modified, for example, CyanogenMod). You can also do any possible (especially dangerous) manipulations that an Administrator can do (for example, deploying a custom kernel). Rooting is not an illegal operation, as you are modifying YOUR device. But not all manufacturers appreciate this practice and usually void the warranty.

Have a go hero – transferring a file to SD card from command line

Using the information provided, you should be able to connect to your phone like in the good old days of computers (I mean a few years ago!) and execute some basic manipulation using a shell prompt. I propose you to transfer a resource file by hand, like a music clip or a resource that you will be reading from a future program of yours.

To do so, you need to open a command-line prompt and perform the following steps:

  1. Check if your device is available using adb from command line.
  2. Connect to your device using the Android Debug Bridge shell prompt.
  3. Check the content of your SD card using standard Unix ls command. Please note that ls on Android has a specific behavior as it differentiates ls mydir from ls mydir/, when mydir is a symbolic link.
  4. Create a new directory on your SD card using the classic command mkdir
  5. .

  6. Finally, transfer your file by issuing the appropriate adb command.

Project configuration tool

The command named android is the main entry point when manipulating not only projects but also AVDs and SDK updates. There are few options available, which are as follows:

  • create project: This option is used to create a new Android project through command line. A few additional options must be specified to allow proper generation:

    -p

    The project path

    -n

    The project name

    -t

    The Android API target

    -k

    The Java package, which contains application’s main class

    -a

    The application’s main class name (Activity in Android terms)

    For example:

    $ android create project –p ./MyProjectDir –n MyProject –t
    android-8 –k com.mypackage –a MyActivity

  • update project: This is what we use to create Ant project files from an existing source. It can also be used to upgrade an existing project to a new version. Main parameters are as follows:

    -p

    The project path

    -n

    To change the project name

    -l

    To include an Android library project (that is, reusable code). The path must be relative to the project directory).

    -t

    To change the Android API target

    There are also options to create library projects (create lib-project, update lib- project) and test projects (create test-project, update test-project). I will not go into details here as this is more related to the Java world.

    As for ADB, android command is your friend and can give you some help:

    $ android create project –help

     

    Command android is a crucial tool to implement a continuous integration toolchain in order to compile, package, deploy, and test a project automatically entirely from command line.

    Have a go hero – towards continuous integration

    With adb, android, and ant commands, you have enough knowledge to build a minimal automatic compilation and deployment script to perform some continuous integration. I assume here that you have a versioning software available and you know how to use it. Subversion (also known as SVN) is a good candidate and can work in local (without a server).

    Perform the following operations:

    1. Create a new project by hand using android command.
    2. Then, create a Unix or Cygwin shell script and assign it the necessary execution rights (chmod command). All the following steps have to be scribbled in it.
    3. In the script, check out sources from your versioning system (for example, using a svn checkout command) on disk. If you do not have a versioning system, you can still copy your own project directory using Unix commands.
    4. Build the application using ant.
    5. Do not forget to check command results using $?. If the returned value is different from 0, it means an error occurred. Additionally, you can use grep or some custom tools to check potential error messages.

    6. If needed, you can deploy resources files using adb
    7. Install it on your device or on the emulator (which you can launch from the script) using ant as shown previously.
    8. You can even try to launch your application automatically and check Android logs (see logcat option in adb). Of course, your application needs to make use of logs!

    A free monkey to test your App!
    In order to automate UI testing on an Android application, an interesting utility that is provided with the Android SDK is MonkeyRunner, which can simulate user actions on a device to perform some automated UI testing. Have a look at http://developer.android.com/guide/developing/tools/monkeyrunner_concepts.html .

    To favor automation, a single Android shell statement can be executed from command-line as follows:

    adb shell ls /sdcard/

     

    To execute a command on an Android device and retrieve its result back on your host shell, execute the following command: adb shell “ls / notexistingdir/ 1> /dev/null 2> &1; echo $?” Redirection is necessary to avoid polluting the standard output. The escape character before $? is required to avoid early interpretation by the host shell.

    Now you are fully prepared to automate your own build toolchain!

NO COMMENTS

LEAVE A REPLY

Please enter your comment!
Please enter your name here