简体   繁体   中英

How do I run my packaged binary in my Android app?

I have an Android app that needs to run a custom binary app I wrote. I already built the binary using ndk and packaged it in the apk under res/raw

I did something like this to first run the su process.

Process process;
process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());

What do I do after this to run the binary from resources? There was another question here that suggested the use of AssetManager but I don't understand how to do it exactly. I checked out some opensource Apps (android-wifi-tether, etc.) that have binaries packaged with them and I don't see AssetManager anywhere in their source and don't understand how exactly they're doing it.

There's a nasty hacky way to trick Android into doing this for you (which I do, successfully).

When the application is installed, Android will copy the appropriate libraries for your architecture out of libs/$ARCH/libfoo.so into /data/data/$PACKAGE/libs for you. The tricky bit is that it will only copy files of the form lib$SOMETHING.so . It'll even preserve the execute permissions.

So, if you rename your su executable to libsu.so , Android will do all the work for you. You can then find it using the paths available from Activity.

However, beware! Android is not designed to run standalone apps and Zygote really doesn't get on well with being forked. I've found that Runtime.exec() has race conditions and can crash. The only reliable technique I've found is to use JNI to implement a little library that does a fork and exec without touching any other data between the fork and the exec. I did have a question here about this with all the details, but I can't find it.

I don't have access to any of the code right now, but if you want I can find some of it for you on Monday.

Adding to David Given's response, which is great, this is what I use at the end of Android.mk to rename the binary automatically. May be of some use to others trying the same thing:

...
LOCAL_MODULE := yourbinarynamehere

include $(BUILD_EXECUTABLE)

all: $(LOCAL_MODULE)
    $(shell (mv libs/$(TARGET_ARCH_ABI)/$< libs/$(TARGET_ARCH_ABI)/lib$<.so))

Mind the TAB before $(shell... spaces won't work as per standard GNU Make.

There some directory already set as a folder named 'jniLibs' by jniLibs.srcDirs in build.gradle file

src/main/jniLibs/arm64-v8a
src/main/jniLibs/armeabi-v7a
src/main/jniLibs/x86
src/main/jniLibs/x86_64

You can change the path by setting in you app build.gradle file:

sourceSets {
    main {
        jniLibs.srcDirs = ['libs']
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM