dcsimg

Writing “C” Code for Android

The Android SDK is strictly for Java Programmers -- however, the Native Development Kit cracks the door to let some "C" inside

Java Only, please

The supported and prescribed manner of creating Android applications is via the Android SDK and that means writing your applications in Java.

But what if you have a large body of code already written in C and you want to take leverage that investment for your Android efforts? Should you port your code to Java? Porting your code may be the right answer, but before you start refactoring your code into Java, you should have a look at the Android Native Development Kit (NDK).

Introduced around the release of Android version 1.5, the Android NDK permits developers to write code in “C” that is then callable from Android applications written in Java. The plumbing between the environments is known as the Java Native Interface, or JNI.

JNI has been around for years as a means to permit Java developers to access vendor SDKs or other available C code. Early on, the majority of software vendors’ SDKs were provided as C language static or dynamic libraries — however, this didn’t do Java programmers much good.

The solution to providing the functionality of those SDKs to Java applications was to write a “wrapper” dll in C. The wrapper implemented the Java Native Interface and then proxies calls to the third-party dll. Over time as Java became more popular, some thoughtful vendors began shipping their libraries Java-ready by providing their own JNI wrappers. Today Android developers can leverage C code with JNI with the help of the NDK.

Using the NDK

The Android NDK is a separate download from the Android development site. The NDK is supported on Linux, Mac OSX and Windows, however Windows users need to install Cygwin in order to run the tools properly.

After downloading the NDK, you need to run a script found in the build subdirectory named host-setup.sh. Before running the script you need to set the environment variable named ANDROID_NDK_ROOT to point to your installation of the NDK. For example, on my machine I perform this with:

export ANDROID_NDK_ROOT=~/Software/android/ndkpath

Running this script does basically two things:

It first verifies that your build tools are compatible and that your paths are properly setup for the C and C++ compilers, and the linker. It also locates the pre-built libraries shipped with the NDK which are specific to the Android environment.

./host-setup.sh

Detecting host toolchain.

CC         : compiler check ok (gcc)
LD         : linker check ok (gcc)
CXX        : C++ compiler check ok (g++)
Generate   : out/host/config.mk
Toolchain  : Checking for arm-eabi-4.2.1 prebuilt binaries

Host setup complete. Please read docs/OVERVIEW.TXT if you don't know what to do.

The script also writes out a file named config.mk into a directory named $ANDROID_NDK_ROOT/build/out/host. This file is used by the build tools.

# This file was autogenerated by host-setup.sh. Do not edit !
HOST_OS       := darwin
HOST_ARCH     := x86
HOST_TAG      := darwin-x86
HOST_CC       := gcc
HOST_CFLAGS   :=
HOST_CXX      := g++
HOST_CXXFLAGS :=
HOST_LD       := gcc
HOST_LDFLAGS  :=
HOST_AR       := ar
HOST_ARFLAGS  := 

Without this file, you cannot build NDK applications. Note that when running the script on my machine, I had to tweak the output directory location for the config.mk file to be written as there was an error in host-setup.sh. I was testing with version 1.5 of the NDK, so it is likely fixed in the latest release (1.6).

The NDK ships with two sample applications to exercise the NDK: a simple “Hello World” application named hello-jni and another project which demonstrates the use of both a static and a dynamic library. In addition to the “C” language components of these projects, the NDK also ships with sample Android Java applications to demonstrate loading and invoking the JNI code.

The NDK has a somewhat sophisticated build environment with a series of make files and make file “snippets” throughout the NDK installation. According to the documentation of the NDK, this build environment is very similar to the core Android source code base.

After getting the hello-jni code to compile, build and run successfully, I thought it would be worth the exercise to build one from scratch — or at least a healthy “cut, paste and modify” version of my own. So I created a simple application and JNI library to perform two basic tasks, each implemented as functions in a C source file. The first function just returns a string and the second increments a passed-in integer, returning the new value as an integer. Of course using JNI for such a task is not worth the effort, but once this is working, more sophisticated tasks are within our reach. Let’s have a quick look.

Building a JNI app

We’ll start by building our JNI C code, implementing the two methods of interest. Here is the C code.

#include <string.h>
#include <jni.h>

jstring
Java_com_msi_linuxmagazine_jnisample_LMJNI_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
    return (*env)->NewStringUTF(env, "Hello from linuxdlsazine!");
}

jint
Java_com_msi_linuxmagazine_jnisample_LMJNI_incrementFromJNI(JNIEnv* env,jobject thiz,jint innumber)
{
	return innumber + 1;
}

Note the funny-looking function names! The methods are named according to the following pattern:

Java_<the fully qualified Java name space with “.” replaced with “_”>_methodname

In our Java code shown below, the Java package name is com.msi.linuxmagazine.jnisample and the class name is LMJNI. Therefore the function prefix is: “Java_com_msi_linuxmagazine_jnisample_LMJNI_”

Once the code is written, we also need a couple of Makefile snippets to grease the skids in the build process. The first file named Android.mk is required to compile the C code.


LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := linuxmagazine
LOCAL_SRC_FILES := linuxmagazine.c

include $(BUILD_SHARED_LIBRARY)

The Java application is stored beneath the ANDROID_NDK_ROOT in a directory named apps. This directory contains a file named Application.mk which tells the NDK where to save the created JNI library file: liblinuxmagazine.so. The Android code is in a sub-directory named project. Here is the contents of the Application.mk file:

APP_PROJECT_PATH := $(call my-dir)/project
APP_MODULES      := linuxmagazine

To build the JNI code, change directory to the base of your NDK installation and run make, along with the specific target we want the build system to compile:

cd $ANDROID_NDK_ROOT
make APP=linuxmagaine V=1

The V=1 makes the output verbose.

To perform a rebuild, add a -B option to the command line above. Here is what the verbose output looks like:

Android NDK: Building for application 'linuxmagazine'
Compile thumb  : linuxmagazine <= sources/samples/linuxmagazine/linuxmagazine.c
build/prebuilt/darwin-x86/arm-eabi-4.2.1/bin/arm-eabi-gcc -Ibuild/platforms/android-1.5/arch-arm/usr/include -march=armv5te -mtune=xscale -msoft-float -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__   -Isources/samples/linuxmagazine -DANDROID  -O2 -DNDEBUG -g    -c -MMD -MP -MF out/apps/linuxmagazine/android-1.5-arm/objs/linuxmagazine/linuxmagazine.o.d.tmp sources/samples/linuxmagazine/linuxmagazine.c -o out/apps/linuxmagazine/android-1.5-arm/objs/linuxmagazine/linuxmagazine.o
build/core/mkdeps.sh out/apps/linuxmagazine/android-1.5-arm/objs/linuxmagazine/linuxmagazine.o out/apps/linuxmagazine/android-1.5-arm/objs/linuxmagazine/linuxmagazine.o.d.tmp out/apps/linuxmagazine/android-1.5-arm/objs/linuxmagazine/linuxmagazine.o.d
SharedLibrary  : liblinuxmagazine.so
build/prebuilt/darwin-x86/arm-eabi-4.2.1/bin/arm-eabi-gcc -nostdlib -Wl,-soname,liblinuxmagazine.so -Wl,-shared,-Bsymbolic  out/apps/linuxmagazine/android-1.5-arm/objs/linuxmagazine/linuxmagazine.o -Wl,--whole-archive  -Wl,--no-whole-archive   build/platforms/android-1.5/arch-arm/usr/lib/libc.so build/platforms/android-1.5/arch-arm/usr/lib/libstdc++.so build/platforms/android-1.5/arch-arm/usr/lib/libm.so   -Wl,--no-undefined   -Wl,-rpath-link=build/platforms/android-1.5/arch-arm/usr/lib /Users/fableson/Software/android/android-ndk-1.5_r1/build/prebuilt/darwin-x86/arm-eabi-4.2.1/bin/../lib/gcc/arm-eabi/4.2.1/interwork/libgcc.a -o out/apps/linuxmagazine/android-1.5-arm/liblinuxmagazine.so
Install        : liblinuxmagazine.so => apps/linuxmagazine/project/libs/armeabi
mkdir -p apps/linuxmagazine/project/libs/armeabi
install -p out/apps/linuxmagazine/android-1.5-arm/liblinuxmagazine.so apps/linuxmagazine/project/libs/armeabi/liblinuxmagazine.so
build/prebuilt/darwin-x86/arm-eabi-4.2.1/bin/arm-eabi-strip --strip-debug  apps/linuxmagazine/project/libs/armeabi/liblinuxmagazine.so

That was fun — now we have our liblinuxmagazine.so sitting in $ANDROID_NDK_ROOT/apps/linuxmagazine/libs/armeabi.

Now let’s create our Android Java application to exercise our JNI code.

The application has two TextView (edit box) fields and two buttons, organized into pairs. The first pair is used to exercise the “get a string” JNI function and the second is used for the “increment a number” function. This image shows the user interface of the application before the buttons are clicked.

Before running JNI code
Before running JNI code

Now, let’s look at the code for this Java application:

package com.msi.linuxmagazine.jnisample;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Button;

public class LMJNI extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button btnGetString = (Button) this.findViewById(R.id.btnGetString);
        btnGetString.setOnClickListener(new Button.OnClickListener() {
        	public void onClick(View v) {
	                TextView label = (TextView) findViewById(R.id.TheLabel);
	                label.setText(stringFromJNI());   // calling a JNI function here!
        	}
        });

        Button btnAddNumber = (Button) this.findViewById(R.id.btnAddNumber);
        btnAddNumber.setOnClickListener(new Button.OnClickListener(){
        	public void onClick(View v) {
	                TextView numberField = (TextView) findViewById(R.id.number);
	                int operand = Integer.parseInt(numberField.getText().toString());
	                int answer = incrementFromJNI(operand);  // calling a JNI function here!
	                numberField.setText("" + answer);
        	}
        });
    }

    // declare the externally provided methods
    public native String  stringFromJNI();
    public native int incrementFromJNI(int number);

    static {
    	// load our JNI library.  Note, leave off the "lib" and the ".so"
        System.loadLibrary("linuxmagazine");
    }
}

And here is the layout for the user interface:

<?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:id="@+id/TheLabel" android:text="LMJNI ..."/>

<Button android:text="Get String" android:id="@+id/btnGetString" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/number" android:text="10" android:numeric="integer"/>

<Button android:text="Add Number" android:id="@+id/btnAddNumber" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

</LinearLayout>

Some things to note in this code snippet:

  • We are using a basic single-Activity Android application with a simple user interface layout: two pairs of TextView and Button.
  • A call to System.loadLibrary loads our JNI shared library.
  • We define each of the implemented methods. Note the native qualifier on the methods.
  • Each user interface element has an “id” attribute so we can get access to it at run-time, a standard Android practice.
  • We create onClick handlers for each button and within those methods, we invoke the native code. These click handlers have no idea that the code is external to the application.
  • If the native methods were missing, the application would throw an exception. The app really should have a try/catch block.

The JNI library is automatically deployed as part of our apk file and the code runs as expected at runtime!

After selecting the buttons we see the string has been returned from the JNI code and the number 10 has been incremented to 11.

After running JNI code
After running JNI code

This is just scratching the surface of using the NDK, but hopefully sheds some light on using C with the Android platform. There is a subset of the system libraries shipped with the NDK — the documentation warns against using other libraries as the underlying architecture is at risk of changing. I personally would not be too concerned with this as the entire mobile space is rapidly changing!

This code was compiled against version 1.5 of the NDK and was found to run just fine against the 1.5 and 2.1 Android emulators.

Comments on "Writing “C” Code for Android"

naturally like your web site but you need to take a look at the spelling on quite a few of your posts. A number of them are rife with spelling problems and I in finding it very troublesome to tell the reality then again I’ll definitely come back again.

Please check out the websites we stick to, which includes this one particular, as it represents our picks through the web.

Very handful of internet websites that come about to be comprehensive below, from our point of view are undoubtedly very well worth checking out.

Hello There. I found your blog using msn. This is a really well written article. I’ll make sure to bookmark it and come back to read more of your useful info. Thanks for the post. I will certainly comeback.

Every when in a even though we choose blogs that we read. Listed beneath are the latest web sites that we opt for.

I don’t even understand how I stopped up right here, however I assumed this publish was once great. I don’t recognize who you are however definitely you’re going to a famous blogger should you are not already. Cheers!

I know of people who are gifted and promote their books that approach quite efficiently. Only they would charge me nearly $2000.00 for a website. I even have no money.

Please stop by the web pages we follow, such as this 1, because it represents our picks from the web.

Everyone loves what you guys are up too. Such clever work and exposure! Keep up the excellent works guys I’ve added you guys to blogroll.

The downside is that this is the type of thing that occurs. When you are new to the sector, folks reap the benefits of the issues you do not know. The backside line is that optimizing your web site takes time.

Somebody essentially lend a hand to make significantly posts I would state. This is the first time I frequented your web page and up to now? I amazed with the analysis you made to make this actual publish extraordinary. Wonderful job!

Check below, are some completely unrelated internet websites to ours, nevertheless, they are most trustworthy sources that we use.

I am curious to find out what blog platform you are using? I’m having some small security issues with my latest site and I would like to find something more safe. Do you have any recommendations?

Here are several of the internet sites we suggest for our visitors.

One of our visitors just lately suggested the following website.

Don’t forget the expense of underwire swimsuits because they are generally in no way that cheap!

Hello, i think that i saw you visited my site so i came to “return the favor”.I am trying to find things to improve my website!I suppose its ok to use some of your ideas!!

Most designers have a web site where you can instantly see their previous work and get a feel for how they design. As a consequence, the ceiling fan blades will move the hot air flow hovering nearby the roof and force it downwards in direction of the person below, specifically where it is wanted. However, if your home is double-glazed, the radiators can be positioned to suit design and space needs since the areas surrounding the windows will be just about as warm as the other walls in the house.

Check beneath, are some entirely unrelated sites to ours, nonetheless, they’re most trustworthy sources that we use.

First off I would like to say excellent blog! I had a quick question which I’d like to ask if you do not mind. I was curious to know how you center yourself and clear your mind prior to writing. I have had a difficult time clearing my thoughts in getting my thoughts out there. I truly do take pleasure in writing however it just seems like the first 10 to 15 minutes are usually lost just trying to figure out how to begin. Any recommendations or hints? Many thanks!

Some folks really feel that spending cash on cleaning services is not worth it since they can clean and preserve their own property. While this may possibly be true, you might not be able to get your residence as clean and spotless as specialist cleaners can.

Here are some hyperlinks to internet sites that we link to simply because we think they’re worth visiting.

This is a topic that’s close to my heart… Take care! Where are your contact details though?

Useful info. Fortunate me I discovered your website accidentally, and I am surprised why this coincidence did not came about earlier! I bookmarked it.

Men Explain Things to Me,” an essay by Solnit, was a sensation when it was initially printed.

Why people still use to read news papers when in this technological world all is available on web?

obviously like your web-site but you need to test the spelling on quite a few of your posts. Several of them are rife with spelling issues and I in finding it very bothersome to tell the truth then again I will certainly come again again.

Usually posts some quite fascinating stuff like this. If you?re new to this site.

five hundredtworevolting disgustingLocalrevolting disgustingfive hundred search engine optimisation extended familyworksrevolting disgustingnuclear familyfive hundred to put five hundredtwoextended familyyounuclear family twoforwardtwo five hundredtwonuclear familyofextended familytwo five hundredextended familyrevolting disgustingthefive hundred competitors, five hundredextended familyandrevolting disgustingtwo the businesses five hundredtwoextended familyrevolting disgustingthatrevolting disgustingtwo perceive five hundrednuclear familyhowextended family essential this is would be the five hundredtwoextended familyonesfive hundred five hundredtwonuclear familytorevolting disgustingtwofive hundred twonuclear familyrevolting disgustingmaximise web extended familyadvertising and marketingextended family.

Heya i’m for the first time here. I came across this board and I find It truly useful & it helped me out a lot. I hope to give something back and aid others like you helped me.

After having examined Shopify for a whole week, we’ve got to admit that we are fairly impressed.

Greetings! Very useful advice in this particular post! It is the little changes that produce the most significant changes. Thanks for sharing!

Every after in a whilst we choose blogs that we study. Listed beneath would be the most current sites that we pick.

This site was… how do you say it? Relevant!! Finally I’ve found something that helped me. Kudos!

If you are going for finest contents like myself, just pay a visit this website everyday since it presents feature contents, thanks

Anxiety attacks occur suddenly and symptoms can mimic other acute well being situations, similar to coronary heart issues.

I am starting an ecomm website to promote costume jewellery. I at present have a wholesale business selling to most US malls. While this is a high volume business at the wholesale stage, I’m not likely sure what to expect quantity wise with an ecomm web site selling directly to the buyer. I can envision (and hope) that this business might be pretty significant. I am not skilled with constructing ecomm sites in any respect, but am not afraid of know-how. In your opinion, is Shopify one of the best platform to start out this ecomm enterprise with, or am I better off just hiring somebody to construct my web site from scratch?

That is a really good tip especially to those new to the blogosphere. Brief but very precise info? Appreciate your sharing this one. A must read post!

You really make it appear really easy with your presentation but I find this topic to be actually something that I believe I’d by no means understand. It kind of feels too complex and extremely large for me. I am taking a look ahead in your next submit, I’ll try to get the grasp of it!

Here are some hyperlinks to sites that we link to because we consider they are really worth visiting.

I might repeat to myself slowly and soothingly, a list of quotations beautiful from minds profound – if I can remember any of the damn things.

Hey very interesting blog!

Check below, are some completely unrelated websites to ours, however, they are most trustworthy sources that we use.

Leave a Reply