如何将已编译的本机库动态加载到Android应用程序中?

时间:2019-05-08 17:53:51

标签: android java-native-interface dynamic-library

我正在尝试将本机库libhello_world.so动态加载到示例Android项目中。我的目标是使应用程序正常运行,并在运行时获取该库并加载它,以便可以使用它。
目前,Android应用程序的结构为

├── 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

我这样加载库

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

我现在想以某种方式无需,显然可以在android项目中拥有文件夹jniLibs,以从系统或URL中的其他路径加载库。例如,假设文件夹jniLibs的内容位于目录/tmp中。我如何在应用程序中指定它以便可以在运行时找到它?

这可能吗?如果可以,怎么办?

1 个答案:

答案 0 :(得分:1)

从某种意义上说,您的任务很简单。 Java定义了System.load(),它应作为

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

loadLibrary()不同,在这里您可以显式指定路径,并且名称不需要以lib开头和.so结尾。仍然,系统可能会对可以从中加载库的路径施加其他限制。例如。您不能从外部存储(即/sdcard)加载库。只有系统应用程序有权从/system/libs加载库(少数白名单库除外)。

但是,正如@CommonsWare在他的评论中解释的那样,Google Play商店和其他已建立的应用程序分发渠道的要求不允许加载库或以其他方式执行来自其(Google Play等)安全渠道的二进制文件

对于jniLinbs文件夹,这不是将本地库注入APK或捆绑包的唯一方法。有多种方法可以强制gradle将一些文件添加到libs部分,以便设备上的应用程序能够使用System.load()加载这些文件。