如何将 JNI 与 AAR 库一起使用?
How do I use JNI with AAR library?
我正在创建一个 Android 库(.aar 文件),我需要使用 JNI。 (我非常清楚 Google 不鼓励尽可能使用 JNI/NDK,但在这种情况下,这是不可能的)。
我从一个独立的hello-jni示例APP开始(初学JNI),有以下文件:
HelloJni.java
public class HelloJni extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText( stringFromJNI() );
setContentView(tv);
}
public native String stringFromJNI();
static {
System.loadLibrary("hello-jni");
}
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := all
你好-jni.c
#include <string.h>
#include <jni.h>
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI!");
}
以下作为应用程序 (apk) 构建良好,我能够 运行 它在我的设备上,按预期打印 "Hello from JNI!"。
现在,我做了同样的事情,但我构建了一个库项目来生成 aar,而不是 apk。除了 HelloJni.java,我将所有文件保持不变,我将其更改为以下内容:
HelloJni.java
public class HelloJni {
public native String stringFromJNI();
static {
System.loadLibrary("hello-jni");
}
}
aar 构建良好,但是当我将 aar 导入一个单独的应用程序项目,并尝试在我的设备上 运行 它时,它在应用程序启动时崩溃并且我收到以下错误 logcat 留言:
com.test.sample.mysampleapplication E/AndroidRuntime﹕ FATAL EXCEPTION:
main
Process: com.test.sample.mysampleapplication, PID: 20047
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file
"/data/app/com.test.sample.mysampleapplication-1/base.apk"],nativeLibraryDirectories=[/data/app/com.test.sample.mysampleapplication-1/lib/arm,
/vendor/lib, /system/lib]]] couldn't find "libhello-jni.so"
at java.lang.Runtime.loadLibrary(Runtime.java:366)
at java.lang.System.loadLibrary(System.java:988) ...
这个 "libhello-jni.so" 文件到底是什么?为什么我需要它?我能够 运行 这作为一个 apk 非常好。但是谁能解释为什么当我把它做成 aar 并将其导入应用程序项目以使用它时它不起作用?我是否缺少将其放入库(并使用它)所需的一些额外步骤?谢谢!
编辑:
这就是我将 aar 导入我的应用程序的方式。
1. 点击"File" -> "New" -> "New Module"。
2. Select "Import .JAR or .AAR Package" 作为模块类型。
3.将我的aar文件设置为新模块
4.然后打开"File" -> "Project Structure"
5. 在 "Dependencies" 选项卡中,添加 "Module dependency" 和 select 我的 aar 文件
如果这不是将 aar 导入我的应用程序的好方法,那么也请告诉我。谢谢!
您必须使用 Android NDK 中的 ndk-build 命令构建本机代码。
此过程将生成将包含在您的构建中的 linhello-jni.so。
原来我必须在我的 AAR 模块目录中的 build.gradle 文件中添加一些 NDK 配置。
build.gradle:
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
// This determines the .so filename
ndk {
moduleName "hello-jni"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
如果不在 build.gradle 中添加,将生成一个默认为项目名称的 .so 文件,在我的例子中是 "libsample-aar.so"。使用上面的配置,生成的 .so 文件将是 "libhello-jni.so".
我正在创建一个 Android 库(.aar 文件),我需要使用 JNI。 (我非常清楚 Google 不鼓励尽可能使用 JNI/NDK,但在这种情况下,这是不可能的)。
我从一个独立的hello-jni示例APP开始(初学JNI),有以下文件:
HelloJni.java
public class HelloJni extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText( stringFromJNI() );
setContentView(tv);
}
public native String stringFromJNI();
static {
System.loadLibrary("hello-jni");
}
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := all
你好-jni.c
#include <string.h>
#include <jni.h>
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI!");
}
以下作为应用程序 (apk) 构建良好,我能够 运行 它在我的设备上,按预期打印 "Hello from JNI!"。
现在,我做了同样的事情,但我构建了一个库项目来生成 aar,而不是 apk。除了 HelloJni.java,我将所有文件保持不变,我将其更改为以下内容:
HelloJni.java
public class HelloJni {
public native String stringFromJNI();
static {
System.loadLibrary("hello-jni");
}
}
aar 构建良好,但是当我将 aar 导入一个单独的应用程序项目,并尝试在我的设备上 运行 它时,它在应用程序启动时崩溃并且我收到以下错误 logcat 留言:
com.test.sample.mysampleapplication E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.test.sample.mysampleapplication, PID: 20047 java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.test.sample.mysampleapplication-1/base.apk"],nativeLibraryDirectories=[/data/app/com.test.sample.mysampleapplication-1/lib/arm, /vendor/lib, /system/lib]]] couldn't find "libhello-jni.so" at java.lang.Runtime.loadLibrary(Runtime.java:366) at java.lang.System.loadLibrary(System.java:988) ...
这个 "libhello-jni.so" 文件到底是什么?为什么我需要它?我能够 运行 这作为一个 apk 非常好。但是谁能解释为什么当我把它做成 aar 并将其导入应用程序项目以使用它时它不起作用?我是否缺少将其放入库(并使用它)所需的一些额外步骤?谢谢!
编辑:
这就是我将 aar 导入我的应用程序的方式。 1. 点击"File" -> "New" -> "New Module"。 2. Select "Import .JAR or .AAR Package" 作为模块类型。 3.将我的aar文件设置为新模块 4.然后打开"File" -> "Project Structure" 5. 在 "Dependencies" 选项卡中,添加 "Module dependency" 和 select 我的 aar 文件 如果这不是将 aar 导入我的应用程序的好方法,那么也请告诉我。谢谢!
您必须使用 Android NDK 中的 ndk-build 命令构建本机代码。
此过程将生成将包含在您的构建中的 linhello-jni.so。
原来我必须在我的 AAR 模块目录中的 build.gradle 文件中添加一些 NDK 配置。
build.gradle:
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
// This determines the .so filename
ndk {
moduleName "hello-jni"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
如果不在 build.gradle 中添加,将生成一个默认为项目名称的 .so 文件,在我的例子中是 "libsample-aar.so"。使用上面的配置,生成的 .so 文件将是 "libhello-jni.so".