8

As a follow up to an earlier question (Android ioctl - root permissions and usage), is it possible to create a separate native executable and package it in an APK?

The app needs root access and isn't going into the Android marketplace, but I'd like to be able to install it without using a script that pushes an extra executable onto the device.

Community
  • 1
  • 1
derekerdmann
  • 17,696
  • 11
  • 76
  • 110

2 Answers2

10

There is an easy way to package an executable into an APK, and let the system installer take care of unpacking this executable, see How to package native commandline application in apk?.

The trick (tested up to Jelly Bean 4.3) is to name the file "libmyexecutable.so" and put it into libs/armeabi of your Android project (I assume an ADT or ant build). The Package Manager will unpack the file to /data/data/your.package.full.name/lib (it's a symbolic link, for backwards compatibility reasons, so maybe in some future version of Android this will not work anymore) on the device, with executable permissions.

Note that the file has all read-and-execute permissions, so you can use Runtime.getRuntime().exec() or system() from other apps, too.

Update: These days, you should use libs/armeabi-v7a for 32 -bit ARM executables, and you probably need to prepare 64-bit ARM version of the same executables, too.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • I tried this, but when I execute the binary, (with `Runtime.getRuntime().exec("/data/data/your.package.full.name/lib/libmyexec.so"`, nothing happens (but the same command works in adb shell). –  May 12 '14 at 21:47
  • @Nutomic: what do you mean "nothing happens"? Did you run same executable from adb shell, or you ran this installed file? And the questions, naturally, are: whether the file was there, whether the permissions were correct, which device and OS version this was? – Alex Cohn May 13 '14 at 11:36
  • Okay I figured it out, tI had to run `Process p = Runtime.getRuntime().exec("sh")`, get the data output stream and do `dos.writeBytes("path/to/lib/libexec.so)`. Thanks :) –  May 13 '14 at 23:03
  • @Nutomic: it was not an executable binary, but a shell script.. Wasn't it? In this case, you don't need eXecutable permission, and don't need this trick. – Alex Cohn May 14 '14 at 04:26
  • It's a binary that expects to run on a shell (takes flags, writes to stdout etc). Anyway, it works now. –  May 14 '14 at 12:35
  • Just for future reference, here's the related source code in AOSP: https://android.googlesource.com/platform/frameworks/base.git/+/7f71764/core/jni/com_android_internal_content_NativeLibraryHelper.cpp#356 – Mygod Jul 22 '18 at 08:23
5

You can put it into assets and copy it to the app's private directory on first run. After you set the executable bit, you should be able to run it.

Nikolay Elenkov
  • 52,576
  • 10
  • 84
  • 84
  • Mind for that you'll need permission android.permission.INSTALL_PACKAGES – weakwire Aug 09 '11 at 15:52
  • 3
    What for? It's not a package, just a file copied to the app's private directory. – Nikolay Elenkov Aug 09 '11 at 16:09
  • This is not working anymore since Android 10. See https://developer.android.com/about/versions/10/behavior-changes-10#execute-permission. – Alexander Dyagilev Dec 16 '20 at 07:09
  • Right, latest SELinux policies block this, even though there are a few ways around it. The 'proper' (least likely to break) way to do it would be to link the executable as a library and have entry point from JNI. If you are running on rooted device per OP's question, should be able to modify the SELinux policy too – Nikolay Elenkov Dec 17 '20 at 06:27