如何将已编译的本机库动态加载到 Android 应用程序中?
How to dynamically load a compiled native library into an Android application?
我正在尝试将本机库 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
中。我如何在应用程序中指定它以便可以在 运行 时间找到它?
这可能吗?如果可能的话如何?
从某种意义上说,你的任务是微不足道的。 Java 定义 System.load()
应该作为
System.load("/tmp/libhello_world.so");
与loadLibrary()
不同,这里明确指定路径,名称不需要以lib
开头,.so
结尾。系统仍然可以对可以加载库的路径施加其他限制。例如。您不能从 外部存储 加载库,即 /sdcard
。只有系统应用程序有权从 /system/libs
加载库(少数列入白名单的库除外)。
但是,正如@CommonsWare 在他的评论中所解释的那样,Google Play 商店和其他已建立的应用程序分发渠道的要求不允许加载库或以其他方式执行并非来自他们的二进制文件(Google 播放等) 安全频道。
至于 jniLinbs
文件夹,这不是将本机库注入 APK 或捆绑包的唯一方法。有不同的方法可以强制 gradle 将一些文件添加到 libs
部分,以便设备上的应用程序能够使用 System.load()
.
加载这些文件
我正在尝试将本机库 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
中。我如何在应用程序中指定它以便可以在 运行 时间找到它?
这可能吗?如果可能的话如何?
从某种意义上说,你的任务是微不足道的。 Java 定义 System.load()
应该作为
System.load("/tmp/libhello_world.so");
与loadLibrary()
不同,这里明确指定路径,名称不需要以lib
开头,.so
结尾。系统仍然可以对可以加载库的路径施加其他限制。例如。您不能从 外部存储 加载库,即 /sdcard
。只有系统应用程序有权从 /system/libs
加载库(少数列入白名单的库除外)。
但是,正如@CommonsWare 在他的评论中所解释的那样,Google Play 商店和其他已建立的应用程序分发渠道的要求不允许加载库或以其他方式执行并非来自他们的二进制文件(Google 播放等) 安全频道。
至于 jniLinbs
文件夹,这不是将本机库注入 APK 或捆绑包的唯一方法。有不同的方法可以强制 gradle 将一些文件添加到 libs
部分,以便设备上的应用程序能够使用 System.load()
.