PocketMagic

PocketMagic

Where Technology meets magic


Android
53 Posts
BlackBerry
6 Posts
Electronics
84 Posts
Hardware
142 Posts
High Voltage
57 Posts
Image processing
5 Posts
iPhone
4 Posts
Linux
2 Posts
Nuclear
27 Posts
Optics
11 Posts
Photography
7 Posts
Photoshop
3 Posts
Research
21 Posts
Reviews
19 Posts
Robotics
9 Posts
Security
9 Posts
Software
90 Posts
Symbian
2 Posts
Tubes
23 Posts
Windows Mobile
11 Posts

Sponsored Links


   

Top Articles!


AVR SDCard FAT support with FatFS | 17525 Views | Rate 36.43
AVR SDCard FAT support with FatFS
Single Chip Computer | 1261 Views | Rate 31.53
Single Chip Computer
3V to 400V regulated inverter for Geiger counters | 2213 Views | Rate 16.89
3V to 400V regulated inverter for Geiger counters
Electric Fence - 20KV pulses for perimeter defense | 13891 Views | Rate 11.82
Electric Fence - 20KV pulses for perimeter defense

   

News & Updates


2014-11-25, Electric Fence - 20KV pulses for perimeter defense

2014-10-29, Statie de monitorizare a radiatiei de fond in Timisoara

2014-10-29, uRADMonitor - Online Radiation monitoring station

2014-10-17, Single Chip Computer

 

  

Android C native development using the NDK under Windows


By Radu Motisan Posted on November 18th, 2010 , 3502 Views (Rate 2.38)



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.



More on PocketMagic:

Bluetooth and iOS - Use Bluetooth in your iPhone apps | 7452 Views | Rate 8.63
Bluetooth and iOS - Use Bluetooth in your iPhone apps
How to set the AVR Fusebits | 5289 Views | Rate 8.46
How to set the AVR Fusebits
Discussing security in online on TV News show | 2180 Views | Rate 7.49
Discussing security in online on TV News show
Atmega8 and Nokia 5110 LCD  | 4324 Views | Rate 7.24
Atmega8 and Nokia 5110 LCD
Google Tango Hackathon in Timisoara | 1490 Views | Rate 7.2
Google Tango Hackathon in Timisoara
Programmatically Injecting Events on Android - Part 1 | 6744 Views | Rate 7.17
Programmatically Injecting Events on Android - Part 1

21 Responses to “Android C native development using the NDK under Windows”

  1. 1
    PocketMagic » Android Native Screen capture application using the Framebuffer:

    […]   « Android C native development using the NDK under Windows […]

  2. 2
    gb:

    Your method also has the benefit of working with the sourcery toolchain on older glibcs (the current android ndk will not work on glibc<2.11, eg, fedora 11).

  3. 3
    duckgrindrr:

    I modified your script a bit to make it work with ndk r5:
    http://ideone.com/lt6BW

    I did run into a problem while compiling a specific project though:
    http://ideone.com/QCj2G

    Seems that there’s a problem with a library somewhere, but I’m only getting started with C and GCC so I’d appreciate it if you could look for a workaround for.

    Thanks :)

  4. 4
    duckgrindrr:

    Correction: The new script: http://ideone.com/d0bFq

  5. 5
    Thomas:

    How does any of this change with NDK r5 having a script to build a standalone tool chain?

    Reading the docs indicates that the built tool chain tools don’t support cygwin drive/path naming scheme and that the NDK build tools normally handle this so if you use your own build system under cygwin you would have to clean this up. I’m not sure I’m following this since the example above uses a build system separate from NDK.

  6. 6
    Standalone toolchain | SRombauts.fr:

    […] http://www.pocketmagic.net/?p=1462 This entry was posted in How-to, NDK, Tools and tagged NDK, standalone toolchain. Bookmark the permalink. ← Android 2.3 NativeActivity […]

  7. 7
    hacker:

    It works on the emulator but when I try to run it on the phone, it says link_image[1995]: failed to link /data/local/test CANNOT LINK EXECUTABLE

  8. 8
    Wes:

    hacker:
    April 9th, 2011 at 9:14 pm

    It works on the emulator but when I try to run it on the phone, it says link_image[1995]: failed to link /data/local/test CANNOT LINK EXECUTABLE

    Maybe it’s not working because it needs to be compiled against the same sdk version as your phone? Dunno if you did that or not, cant think of anything else

  9. 9
    Matt Falcon:

    I don’t usually give up on something very easily. And this… this article… does NOT WORK AT ALL! OK, so I just wasted about 4 hours trying to download, extract, configure, DEBUG, DEBUG, TRACE, DEBUG, SEARCH, DEBUG SOME MORE… read, read, read, check, check, POP SOME FREAKING PAIN PILLS… No. This does NOT work.

    For one thing, the article is outdated… you don’t freakin’ get the old r4b version anymore, I get r5c. Completely different paths. Chaining together that OBSCENELY LONG “path”? Made my head pound. Swapping all the backslashes for forwards. Referencing the relative “/home” path (the HELL am I putting that crap in my C: root, it goes on F: with the rest of the Cygwin sprawling mess). Does it work? No. Does the file exist? YES. IT DOES. Not found: crtbegin_dynamic.o. Not found. Not found. Not found. File does not exist. FILE IS RIGHT FREAKING THERE, right where it says it doesn’t exist. That exact string it quotes. It exists. It says it doesn’t.

    I swear to god, I loathe the Linux world, with all my nerdraeg. So much broken code, sleazy hacks, shortsighted scripting, careless changes, and COMPLETE lack of organization. Utter chaos. God, it pisses me off so much that I’m sitting here having my computer tell me that a file DOESN’T exist, and there is no information anywhere online for this stuff. You know what? This kind of crap happens every time I try to do something cool with Android, too.

    I think I’ll go back to compiling a native build environment on the phone itself, thanks. I don’t mind waiting for my phone to compile its own programs. At least I know it’ll work, and I don’t have to trash my own PC with this Cygwin bloatware in order to make a single damn compile!

  10. 10
    TK:

    Great article, I used the (to date) latest NDK r6 and built the sample on a Ubuntu 11.04 host. My target Android platform is a BeagleBoard (OMAP TI) w/pre-built Android 2.3.4 (Gingerbread) available from TI’s site. This saved me a lot of time sifting through the NDK documentation, thumbs up!

  11. 11
    Radu Motisan:

    thanks!

    would love to see your beagleboard. can you post a pic?

  12. 12
    TK:

    Hi Radu,

    Sure no problem would be glad to post a pic (at least in return!). Not sure how to post a pic here? Just let me know how you prefer and an example. I’ll take a picture showing adb shell’s execution of the app (or can also show it on the Android Terminal app?).

    Quick question if you don’t mind. I also have your NativeScreen Capture working (partially….) as well on my Beagleboard (rev c4). However the framebuffer is using 32 bpp, as I’m using the DVI output for video display. So you have only conversion for 24, so I need to add 32 bpp support I just haven’t researched the changes yet. I think it’d be good to include as everyone else out there who has the Beagleboard will probably thank you :) If you have the code for it I can test it immediately or guide me through the changes. I will also work on it.

    FYI – I dumped out some runtime data from your program running on the Beagleboard:

    # ./fb_grabber

    vi.xres = 640
    vi.yres = 480
    vi.xresv = 640
    vi.yresv = 2880
    vi.xoff = 0
    vi.yoff = 2400
    vi.bits_per_pixel = 32
    fi.line_length = 2560
    main() – 4
    vi.xres = 640
    vi.yres = 480
    vi.xresv = 640
    vi.yresv = 2880
    vi.xoff = 0
    vi.yoff = 2400
    vi.bits_per_pixel = 32
    fi.line_length = 2560
    main() – 5
    depth [32] – 6

    Of course the program exits in the switch case for bpp 32.

    Cheers!
    -Tom

  13. 13
    anand:

    Hi,

    I want to write JNI for existing c code, I have c code and header, i
    created the .so file using cygwin, I wrote the Android.mk file and
    using cygwin created the shared library first it was showing
    “undefined reference to function name” error, then I removed “include $
    (CLEAR_VARS)” and again run the ndk-build command then shared library
    was created but while running it was showing UnsatisfiedLinker
    Error.my make file is
    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_MODULE := test
    LOCAL_SRC_FILES := libtest.so

    include $(PREBUILT_SHARED_LIBRARY)

    #LOCAL_PATH := $(call my-dir)

    #include $(CLEAR_VARS)

    LOCAL_C_INCLUDES := $(LOCAL_PATH)

    LOCAL_MODULE := jni_anand
    LOCAL_CPP_EXTENSION := .cpp
    LOCAL_SRC_FILES := anand.cpp
    LOCAL_SHARED_LIBRARY := test

    include $(BUILD_SHARED_LIBRARY)

    Thanks…

  14. 14
    DroidVPN:

    Hi,

    I cant find “build/prebuilt/($OS)/arm-eabi-4.2.1/bin/arm-eabi-gcc” on my copy of NDK (r6b). There is no prebuild directory inside of the build directory. Is the paths changed on my version of NDK?

    Thanks

  15. 15
    Radu Motisan:

    I didn’t use the new one yet, but Google has a habit now, of breaking everything with each new release.

  16. 16
    zerodog:

    You really don’t need to even install cygwin for native android apps, just use your GCC from Android NDK:
    1. create setenv4.bat file (for android 1.6) in your NDK root, and copy the following content to it:

    @rem Change the two paths below to match your installation
    @set SDK_ROOT=C:\android
    @set NDK=%SDK_ROOT%\ndk-r6
    @set PLATFORM=%NDK%\platforms\android-4
    @set PATH=%NDK%\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\arm-linux-androideabi\bin;%PATH%
    @set PATH=%NDK%\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\libexec\gcc\arm-linux-androideabi\4.4.3;%PATH%
    @set PATH=%SDK_ROOT%\sdk\platform-tools;%PATH%
    @set lib=%NDK%\lib-swift;%PLATFORM%\arch-arm\usr\lib
    @set DEPS=-I%PLATFORM%\arch-arm\usr\include -Xlinker -s –sysroot=%PLATFORM%\arch-arm\usr -B %NDK%\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\lib\gcc\arm-linux-androideabi\4.4.3
    @set GCC=gcc %DEPS%
    @echo 1. navigate: cd projects\native\NativeScreenCapture
    @echo 2. Compile: gcc %%DEPS%% -o file file.c
    @echo or: %%GCC%% -o file file.c
    @rem to use ADB, execute this: @set path=C:\android\sdk\platform-tools;%PATH%
    @echo 3. Copy: adb push file /folder/file
    @echo 4. Allow Run: adb shell chmod 555 /folder/file
    @echo 5. Execute: adb shell /folder/file
    @rem keep the console open
    @cmd /k

    2. Run that bat file and follow the instructions.
    cd
    %gcc% -o file1.c file2.c file3.c …

  17. 17
    Radu Motisan:

    Nice one, Zerodog!

  18. 18
    mauro:

    Hi, thanks for the tutorial, it’s been really helpfull.
    Do you know how can i build an static or shared library?

    Thanks in advance.

  19. 19
    veera:

    Veera:

    Very useful tutorial,thank you very much for taking time to write. I tried with Android-ndk-r7, it gave me some problems like can’t find /sys/ctypes.h. After setting up the tools as per the android-ndk native tools setup document everything started working. Script provided by NDK copied compiler tools and sysroot to one folder, that fixed all my issues.

    Thanks,
    Veera

  20. 20
    Dominik:

    Thank you Zerodog… PERFECT!

  21. 21
    Programmatically Injecting Events on Android – Part 2 « PocketMagic:

    […] library uses JNI, and you will need to setup Android NDK if you want to change it or compile […]

Thank you for commenting. Your comment won't show until approved, which can take some time.