14

I would like to package an Android native commandline application into an apk. I have the application building with ndk-build which uses jni/Android.mk. The output is in libs/armeabi/<MyApp>. I also have the apk building with ant. However, the apk does not seem to pick up the commandline application. If I unzip the apk the app is not in there.

What do I need to do to get ant to include a pre-built commandline app?

Also, what do I need to do so that ant runs ndk-build? (This was already answered: Android NDK build with ANT script)

Community
  • 1
  • 1
Alex I
  • 19,689
  • 9
  • 86
  • 158

2 Answers2

14

See Android NDK build with ANT script.

You can add the binary to APK using aapt if Ant does not copy it automatically from libs/armeabi, see Documentation for aapt element in Ant script.

I believe that the file will be correctly extracted to /data/data/your.package.full.name/lib, with executable permissions.

Ant build involves a step called "ApkBuilder", which only adds files from libs/armeabi that match pattern ^.+\.so$ or gdbserver - the latter for debug build only.

But it is not enough to rename the executable to "myexecutable.so": this file will not be extracted by the APK installer on the device.

It is enough to rename the executable to "libmyexecutable.so": this file will be extracted by the APK installer Package Manager on the device to /data/data/your.package.full.name/lib, with executable permissions.

I personally like to give this not-actually-a-library some special name, e.g. lib...ffmpeg...so.

UPDATE 6 years and 12 API levels later, this approach is still valid. But with Android App Bundle, the default behavior of the package manager is not to extract the native libraries from the APK, using them in-place. Here and in comments to this answer, you will find some workarounds for that. The one that is especially attractive, is to refer to the executable as "/path/to/MyApp.apk!lib...ffmpeg...so", but I have not tested this notation does not work with System.exec(). See IssueTracker for discussion.

Note that now there is a special exception for wrap.sh.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • I did this, sure I can add an ant task to run ndk-build and it works. Ant does not automatically copy the executable. I can also add the binary with aapt (either from commandline or ant). Unfortunately, the resulting apk does not install? (manifest error of some kind) The executable is definitely in the apk, as can be checked with unzip. This was helpful but doesn't completely do the job, do you have more suggestions? – Alex I Jul 06 '13 at 09:08
  • OK, here is a way to cheat: call your executable "gdbserver", and it will be both packaged correctly to `lib/armeabi` directory in the APK, and installed to the `/data/data/your.package.name/lib` directory on device. As you noticed, there are two obstacles. One, adding the binary to APK, can be performed as a custom ANT step, but you should take care to have it there before the APK is signed. The second step, on the device, might be trickier. – Alex Cohn Jul 07 '13 at 21:13
  • It happens so that the Package Manager on device looks for `^lib.+\.so$` pattern when it copies native libraries to `/data/data/your.package.name/lib` (which is a symlink on Androoid 4.2). Therefore, see updated answer. – Alex Cohn Jul 08 '13 at 10:15
2

In general, you should put your commandline app into Assets folder, then use AssetManager in order to extract your asset (do not forget to chmod it after extraction!). But there will be a problem where to extract it to, because not every directory in Android may store executable binaries. On Android 2.2 I've tried /cache and it works. Cann't say for newer Androids. Sorry, can give no recommendations regarding ant.

trashkalmar
  • 883
  • 5
  • 11
  • I am trying to do this for android 4.0/4.1/4.2. Executable binaries in /data/local work. – Alex I Jul 06 '13 at 09:09
  • 3
    /data/local is write (and quite possibly also read) restricted on many android releases. Probably the best place to put it is in the private storage of an app, but set the permissions on the file to globally readable and executable if the intent it to share it with other apps or the adb shell. – Chris Stratton Jul 07 '13 at 21:36
  • This doesn't work anymore on Android 10+ https://developer.android.com/about/versions/10/behavior-changes-10#execute-permission – Herz3h Jul 24 '20 at 09:33