mghareeb
mghareeb

Reputation: 129

Where should I add binary executables in an Android project?

So, I have this native code that I built for different CPUs. I don't want to load as a library, I want to execute the binaries through runtime.exec(...).

Is there a way of placing them in some place where Android will take care of the CPU qualifiers? Or do I have to make different APKs?

Upvotes: 0

Views: 3001

Answers (3)

Rabe Arshad
Rabe Arshad

Reputation: 1

I also tried using libiperf3. So file as suggested by @Alex Cohn but still get the permission denied error.

Error Output: Iperf3:error - unable to create a new stream: permission denied

I got the same error when I was trying to execute /data/local/tmp/iperf3 binary using adb shell.

However, when ran chmod 777, I was able to run it successfully. The issue is the app cannot execute it no matter where I put the binary.

Upvotes: 0

Hex24
Hex24

Reputation: 61

Android Q+ (Personally tested with Android 11). Since got released new policy changes towards android system safety, you can't execute normally your binary executables just from /data/data/package/files/... folders.

W^X violation details: https://developer.android.com/about/versions/10/behavior-changes-10#execute-permission

Solution:

1. Add your executables to the native libraries folder in Android studio eg. app/libs/armeabi/executable.

File structure here

2. Also add this line to your manifest (Application layer):

<Application
...
     android:extractNativeLibs="true">
...
</application>

If you are using newer version of the Gradle plugin, you may face issues when your executable not being packaged into apk or extracted in.

/data/app/package/lib/.../...


You need then trick Android Gradle plugin a bit.

Solution:

1. Create a folder structure in your file explorer lib/armeabi/executable (I use armeabi just as an example, it can be your architecture)

2. Now zip this lib folder and rename it to yournaming.jar

3. Copy and paste in your Android Studio libs directory

should look like this

4. Go to your build.grade(app), in dependencies section add following line for compiling .jar.

dependencies {
    implementation fileTree(dir: 'libs', include: '*.jar')
    ...
}

5 Build your .apk and check with analyze tool, folder should be now created in .apk itself

If all these steps done, now can try do exec command to run binary executable from android app:

try {
    // creating exec process
    Process process = 
    Runtime.getRuntime().exec(getApplicationInfo().nativeLibraryDir + 
"/executable");
    // reading and printing executable outcome
    byte[] buffer = new byte[2048];
            process.waitFor();
            process.getInputStream().read(buffer, 0 , buffer.length);
            System.out.println(new String(buffer));

} catch (IOException | InterruptedException e) 
{
        e.printStackTrace();
}

Hopefully helped to solve your case

Upvotes: 5

Alex Cohn
Alex Cohn

Reputation: 57183

Making different APKs is sometimes a good choice, to reduce the download size. Just think about it, hundreds of thousands of people will be downloading these extra megabytes from the Play Store with every update! There are some strategies for creating and maintaining such split APK's: it's important to keep the version numbers in proper order. See https://stackoverflow.com/a/20029256/192373 and the improvement by Ashwin S Ashok below.

Whether you choose to split the APK's, or keep a monolithic one, feel free to use my "patent": put your executables into libs/armeabi-v7a (or other subfolder, according to target ABI) , and give them names that all start with lib and end with .so (e.g. lib_vim_.so). This will turn on the installation magic, and the appropriate files will be unpacked (and updated) into your /data/package/lib folder with executable permissions.

Upvotes: 5

Related Questions