facebooktwittergoogle_pluslinkedinrssyoutubefacebooktwittergoogle_pluslinkedinrssyoutube

A lot has changed since my previous article, on Android C native development, back in 2009.
The Android NDK has been released and the JNI development is not only possible, but also easy. Have a look on this article on the Android NDK.
The new challenge is to use the NDK to compile Native ARM-EABI executables that would run on an Android phone. I don't want to setup the complete Google Android source code as I did in my first article.

This is possible, and I will provide the steps to do it:
Step 1. Install the NDK
Step 2. Install Cygwin
(as presented in the Android NDK Article)
While this guide is for Windows, you can easily adapt the following for a Linux box or a Mac.

Create a simple C code file, test.c

  1.  
  2. #include <stdio.h>
  3.  
  4. int main()
  5. {
  6. printf("Hello Google Android world!\nwww.pocketmagic.net\n");
  7. return 1;
  8. exit(0);
  9. }
  10.  

Find the following locations:
NDK_ROOT (eg. D:\work_code\android\android-ndk-r4b\ )
NDK_ROOT\build\platforms\
NDK_ROOT\build\prebuilt\windows\arm-eabi-4.2.1\
You will need them.

When starting Cygwin using the Cygwin.bat BATCH File, make sure you define the PATH to the Android NDK:

  1.  
  2. set PATH=D:/work_code/android/android-sdk-windows/tools;D:/work_code/android/android-ndk-r4b;D:\work_code\android\android-ndk-r4b\build\prebuilt\windows\arm-eabi-4.2.1\bin\;$PATH;D:\work_code\android\android-ndk-r4b\build\platforms\android-5\arch-arm\usr\lib\;
  3.  

Step 3. If you read my Android NDK article, you already know the NDK folder contains the ndk-build script, that is used to compile the JNI code.
We will build a similar script, to compile our test.c code file.

Let's call this file ndk-comp and place it where ndk-build is.

  1.  
  2. #!/bin/sh
  3.  
  4. OS='windows'
  5. ANDROIDSDK='android-3'
  6.  
  7. PROGDIR=`dirname $0`
  8. PROGDIR=`cd $PROGDIR && pwd`
  9.  
  10. ARMEABIGCC=$PROGDIR/build/prebuilt/$OS/arm-eabi-4.2.1/bin/arm-eabi-gcc
  11. ARMEABILIB=$PROGDIR/build/platforms/$ANDROIDSDK/arch-arm/usr/lib
  12. ARMEABIINC=$PROGDIR/build/platforms/$ANDROIDSDK/arch-arm/usr/include
  13. ARMEABICRT=$PROGDIR/build/platforms/$ANDROIDSDK/arch-arm/usr/lib/crtbegin_dynamic.o
  14.  
  15. LINKER=/system/bin/linker
  16.  
  17. echo "GCC:"$ARMEABIGCC "LIB:"$ARMEABILIB "LINKER":$LINKER "PARAMS:"$@
  18.  
  19. $ARMEABIGCC $@ -Wl,-rpath-link=$ARMEABILIB,-dynamic-linker=$LINKER -L$ARMEABILIB $ARMEABICRT -I$ARMEABIINC -nostdlib -lc
  20.  

If you did everything correctly, you should be able to call this script from within Cygwin's shell. Using cd command, navigate in Cygwin shell to the test.c folder. Compile it using ndk-comp -o test test.c :
compile android native c file using ndk 1
As you can see, running it on the device using ADB works. Here is another picture showing the executable started using the Terminal app, directly on the Android smartphone:
compile android native c file using ndk 2
It works well.

There is another even better way of compiling native C apps for Android using the NDK, as presented by Mamadou on his blog.
You can create a Makefile in the same folder with test.c then navigate there with the Cygwin shell and run make.
The Makefile is as follows:

  1.  
  2. APP := test
  3. ROOT:=/cygdrive/d/work_code/android
  4. NDK_PLATFORM_VER := 3
  5. INSTALL_DIR := /data/tmp
  6.  
  7. ANDROID_NDK_ROOT:=$(ROOT)/android-ndk-r4b
  8. ANDROID_NDK_HOST:=windows
  9. ANDROID_SDK_ROOT:=$(ROOT)/android-sdk-windows
  10. PREBUILD:=$(ANDROID_NDK_ROOT)/build/prebuilt/$(ANDROID_NDK_HOST)/arm-eabi-4.4.0
  11. BIN := $(PREBUILD)/bin
  12.  
  13. CPP := $(BIN)/arm-eabi-g++
  14. CC := $(BIN)/arm-eabi-gcc
  15. CFLAGS := -I$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/include
  16. LDFLAGS := -Wl,--entry=main,-rpath-link=$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib,-dynamic-linker=/system/bin/linker -L$(ANDROID_NDK_ROOT)/build/platforms/android-$(NDK_PLATFORM_VER)/arch-arm/usr/lib
  17. LDFLAGS += -nostdlib -lc -disable-multilib
  18.  
  19.  
  20. all: $(APP)
  21.  
  22. OBJS += $(APP).o
  23.  
  24. $(APP): $(OBJS)
  25. $(CPP) $(LDFLAGS) -o $@ $^
  26.  
  27. %.o: %.c
  28. $(CC) -c $(INCLUDE) $(CFLAGS) $< -o $@
  29. install: $(APP)
  30. $(ANDROID_SDK_ROOT)/tools/adb push $(APP) $(INSTALL_DIR)/$(APP)
  31. $(ANDROID_SDK_ROOT)/tools/adb shell chmod 777 $(INSTALL_DIR)/$(APP)
  32.  
  33. shell:
  34. $(ANDROID_SDK_ROOT)/tools/adb shell
  35.  
  36. run:
  37. $(ANDROID_SDK_ROOT)/tools/adb shell $(INSTALL_DIR)/$(APP)
  38.  
  39. r: $(APP)
  40. $(ANDROID_SDK_ROOT)/tools/adb push $(APP) $(INSTALL_DIR)/$(APP)
  41. $(ANDROID_SDK_ROOT)/tools/adb shell chmod 777 $(INSTALL_DIR)/$(APP)
  42. $(ANDROID_SDK_ROOT)/tools/adb shell $(INSTALL_DIR)/$(APP)
  43.  
  44. clean:
  45. @rm -f $(APP).o $(APP)
  46.  

Makefile
If you copy paste this, make sure you replace the spaces before "$(CPP) $(LDFLAGS.." and the other paragraphs with one TAB. Not doing so will result in an error:

  1.  
  2. $ make
  3. Makefile:24: *** missing separator. Stop.
  4.  
  5. ITX@itxserv /cygdrive/d/work_code/android/TBTS/Native
  6.  

If everything is in place, you can use the following defined commands:
make clean - will delete all object files and prepare for a new build
make - will compile your code
make r - copies the compiled binary to your Android device, it sets executable permissions and launches it.

Here's an image showing that:
compile android native c file using ndk 3

For some reason this binary produces a segmentation fault, just before it terminates. I didn;t have the time to look into this, but Mamadou also had the error. For the moment I'd suggest you stick to my first script.

(Visited 20 times, 2 visits today)
facebooktwittergoogle_plusredditpinterestlinkedinmailfacebooktwittergoogle_plusredditpinterestlinkedinmail
Tagged on: