46

I have a Device on which I installed Android Gingerbread 2.3.4 Here i want to run C executable file on android device

I am able to run android NDK application on this Device and it runs perfect. But I want to run only one hello.c executable file on the Device.

/* #includes #defines ... */

int main(){
    // Do something when this is executed
    return 0;
}

Is there any way to compile this file with Android NDK tool chain so I can run this file's executable?

I found one thing here but this is not working for me. I am using Android NDK, Revision 7b for Linux. There is no directory structure like this.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
user1089679
  • 2,328
  • 8
  • 41
  • 51
  • [How to build an executable for Android shell](https://stackoverflow.com/q/35231168/3290339) – Onik Oct 31 '18 at 21:50
  • I generally do this simply inside the app TERMUX which gives you a working unix terminal – tinyfiledialogs Mar 09 '23 at 17:10
  • See the [official guide(s)](https://developer.android.com/ndk/guides/build), most of the answers here are outdated. For the easiest method (one line compile, no build system), see [this](https://developer.android.com/ndk/guides/other_build_systems). – user_ Jun 09 '23 at 12:41

5 Answers5

40

First, let me say that my answer is dependent on your using NDK r7b (it'll work for r7c as well) on Linux (change paths appropriately for other systems).

Edit: Last tested with NDK r8e on Linux and Nexus 4 with adb from SDK Platform-Tools Rev 18 on Windows 7 (latest as of 2013-07-25) without root access.

Yet Another Edit: Please read this question for altering my instruction for native binaries that need to run on Android 5.0(Lollypop) and later.

  1. Go to $NDK_ROOT (The topmost folder of NDK zip when unzipped).
  2. Copy $NDK_ROOT/samples/hello-jni directory as $NDK_ROOT/sources/hello-world.
  3. Go to $NDK_ROOT/sources/hello-world.
  4. Edit AndroidManifest.xml to give the application an appropriate name (This is optional).
  5. Go to $NDK_ROOT/sources/hello-world/jni. This is where the source code is.
  6. Edit hello-jni.c, remove all the code, and put in your hello world code. Mine is:
    #include 
    int main( int argc, char* argv[])
    {
        printf("Hello, World!");
        return 0;
    }
  7. Edit Android.mk and change the line include $(BUILD_SHARED_LIBRARY) to include $(BUILD_EXECUTABLE). You can also change the LOCAL_MODULE line to the name you want for your executable(default is hello-jni)
  8. Go back to $NDK_ROOT/sources/hello-world
  9. Run ../../ndk-build to create the executable.
  10. Copy it from $NDK_ROOT/sources/hello-jni/libs/armeabi/hello-jni to /data/local/tmp on the Android device and change it's permissions to 755 (rwxr-xr-x). If you changed the LOCAL_MODULE line in $NDK_ROOT/sources/hello-world/jni/Android.mk, the executable name will be the new value of LOCAL_MODULE instead of hello-jni. (All this is done via adb from the Android SDK.)
  11. Execute the binary with full path as /data/local/tmp/hello-jni, or whatever you named it to.

And you're done( and free to start on the documentation in $NDK_ROOT/docs to get a better idea of what to do).

Community
  • 1
  • 1
Samveen
  • 3,482
  • 35
  • 52
  • 5
    There is `test-libstdc++` project under samples directory which looks like exactly what you are try to explain. – m039 Mar 27 '13 at 22:34
27

The best/easiest place to put a executable is /data/local. You'll also need to chmod the binary as executable. Often you'll also need to do this in two steps to get the binary from /sdcard/ to /data/local:

$ adb push mybin /sdcard/
$ adb shell
$ cp /sdcard/mybin /data/local/mybin
$ cd /data/local
$ chmod 751 mybin

Caveats:

  • Not all systems have cp. You can use cat if this is the case:

    $ cat /sdcard/mybin > /data/local/mybin

  • Some systems don't allow write in /data/local for the "shell" user. Try /data/local/tmp

NuSkooler
  • 5,391
  • 1
  • 34
  • 58
  • Are you saying that the binary itself crashes when it runs? If that is the case I suggest you open a new question the specific issue(s) there. – NuSkooler Mar 26 '12 at 17:09
  • Where i am saying? i cant able to Execute this C binary files. how can i achieve this? – user1089679 Mar 26 '12 at 17:19
  • Yes, you need root to play outside the bounds of your application's sandbox. – NuSkooler Jun 21 '13 at 16:38
  • 2
    Incorrect, you **do not** need root, you simply must put the binary in a location writable by the app, such as its private directory. – Chris Stratton May 30 '14 at 18:37
  • 1
    Further, there's no need to push the file to the scard and then move it to /data/local (or more likely, /data/local/tmp) - if you can move it there, you can put it there with adb push to begin with. – Chris Stratton Nov 06 '14 at 19:04
  • Does this still work on Lollipop or Marshmallow? Seems once I update the OS I start getting permission errors. – Ethan_AI Jan 20 '16 at 00:54
  • I didn't find `/data/local` on my (unrooted) Android device, but I installed a Terminal app (e.g., https://f-droid.org/repository/browse/?fdfilter=Terminal&fdid=jackpal.androidterm ) and was able to copy the file into its "home" (`~` in its shell). It's a place where it can be made executable with `chmod 0755 mybin` (only numeric specification of the mode worked). `~` was `/data/data/jackpal.androidterm/app_HOME` – imz -- Ivan Zakharyaschev Aug 12 '16 at 19:08
12

I recently had the same problem on a new nexus-5. I'd like to add that /data/local was not writable by the user ("shell", uid 2000) I got with adb shell. But putting the executable in the subdirectory /data/local/tmp/ worked fine.

Niels Möller
  • 146
  • 1
  • 2
12

the "/sdcard" location is not executable, meaning that any file there is not executable at all.

the only way to "adb push" executable would be to put them in "/data/local", which should be writable for adb, and allow execution for anyone.

dvhh
  • 4,724
  • 27
  • 33
6

In a nutshell,

First, to cross-compile your C code from your host machine, use NDK toolchain with sysroot option and position independent option -fPIE -pie.

$NDKROOT/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-gcc \
--sysroot=$NDKROOT/platforms/android-22/arch-arm64 -fPIE -pie main.c -o main

Note that the arch part aarch64 or aarch-arm64, the toolchain version part 4.9, platform version part android-22, and the binary format for your host machine darwin-x86_64 may vary by your environment.

Second, push your binary under /data/local/tmp and execute it from adb shell.

ddaniel91
  • 15
  • 5
9re
  • 2,408
  • 27
  • 27