4

I am trying to dynamically load a native library libhello_world.so into an example Android project. My goal is the application to run normally and at runtime to fetch the library and load it so it can be used.
Currently the structure of the android app is

├── AndroidManifest.xml
├── java
│   └── example
│       └── myapp
│           └── some
│               └── exampleapp
│                   ├── Computation.java
│                   └── MainActivity.java
├── jniLibs
│   ├── arm64-v8a
│   │   └── libhello_world.so
│   ├── armeabi-v7a
│   │   └── libhello_world.so
│   ├── x86
│   │   └── libhello_world.so
│   └── x86_64
│       └── libhello_world.so
└── res
    ├── layout
    │   └── activity_main.xml
    ├── mipmap-hdpi
    │   ├── ic_launcher.png
    │   └── ic_launcher_round.png
    ├── mipmap-mdpi
    │   ├── ic_launcher.png
    │   └── ic_launcher_round.png
    ├── mipmap-xhdpi
    │   ├── ic_launcher.png
    │   └── ic_launcher_round.png
    ├── mipmap-xxhdpi
    │   ├── ic_launcher.png
    │   └── ic_launcher_round.png
    ├── mipmap-xxxhdpi
    │   ├── ic_launcher.png
    │   └── ic_launcher_round.png
    └── values
        ├── colors.xml
        ├── dimens.xml
        ├── strings.xml
        └── styles.xml

I load the library like this

    static {
        System.loadLibrary("hello_world");
    }

I would like now to be able somehow without obviously having the folder jniLibs in the android project, to load the library from another path in the system or a URL. Imagive for example that the contents of the folder jniLibs are located at the directory /tmp. How would I specify that within the application so it can be found at runtime?

Is this possible and if yes how?

kampias
  • 459
  • 1
  • 10
  • 21
  • 1
    Bear in mind that even if you get this working, you will not be allowed to distribute your app on the Play Store (and possibly other distribution channels). Securing what you want ("at runtime to fetch the library and load it so it can be used") is exceptionally difficult. – CommonsWare May 08 '19 at 17:56
  • @CommonsWare oh I did not know that there is a limitation like this for Play Store applications. Besides that though I would like to see how this can be done cause I could not find anything similar. I already did something like this using java classes which I dynamically load at runtime using `urlClassLoader` and maybe there is something similar for native libs. – kampias May 08 '19 at 18:06
  • 2
    "I already did something like this using java classes which I dynamically load at runtime" -- that too is difficult to secure. Dynamic downloading of JARs is prohibited for Play Store distribution. See https://play.google.com/about/privacy-security-deception/malicious-behavior/, "Apps or SDKs that download executable code, such as dex files or native code, from a source other than Google Play". – CommonsWare May 08 '19 at 18:09

1 Answers1

3

In some sense, your task is trivial. Java defines System.load() which should work as

System.load("/tmp/libhello_world.so");

Unlike loadLibrary(), here you specify the path explicitly, and the name is not required to start with lib and end with .so. Still the system may impose other restrictions on the path from which a library can be loaded. E.g. you cannot load a library from external storage, i.e. /sdcard. Only system apps have permission to load libraries from /system/libs (except the few whitelisted libraries).

But, as @CommonsWare explained in his comment, the requirements of Google Play Store and other established app distribution channels do not allow loading libraries or otherwise executing binaries that don't come from their (Google Play, etc.) secured channels.

As for jniLinbs folder, this is not the only way to inject native libs into an APK or bundle. There are different ways to force gradle to add some files to the libs section, so that the app on device will be able to load these with System.load().

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • I was testing this and still am. I am trying to resolve some permissions issues but I am uncertain if it is related with the way the library is loaded. Though I believe the answer covers the question asked. – kampias May 10 '19 at 16:47