【问题标题】:How do I use JNI with AAR library?如何将 JNI 与 AAR 库一起使用?
【发布时间】:2015-10-23 13:01:19
【问题描述】:

我正在创建一个 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

hello-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!”正如预期的那样。

现在,我做了同样的事情,但我没有使用 apk,而是构建了一个库项目来生成 aar。除了 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: 致命异常: 主要的 进程:com.test.sample.mysampleapplication,PID:20047 java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip 文件 "/data/app/com.test.sample.mysampleapplication-1/base.apk"],nativeLibraryDirectories=[/data/app/com.test.sample.mysampleapplication-1/lib/arm, /vendor/lib, /system/lib]]] 找不到“libhello-jni.so” 在 java.lang.Runtime.loadLibrary(Runtime.java:366) 在 java.lang.System.loadLibrary(System.java:988) ...

这个“libhello-jni.so”文件到底是什么?为什么我需要它?我能够以 apk 的形式完美运行它。但是任何人都可以解释为什么当我将它变成 aar 并将其导入应用程序项目以使用它时它不起作用吗?我是否错过了将其放入库(并使用它)所需的一些额外步骤?谢谢!

编辑:

这就是我将 aar 导入我的应用程序的方式。 1. 点击“文件”->“新建”->“新建模块”。 2. 选择“Import .JAR or .AAR Package”作为模块类型。 3.将我的aar文件设置为新模块 4.然后打开“文件”->“项目结构” 5.在“依赖项”选项卡中,添加“模块依赖项”并选择我的aar文件 如果这不是将 aar 导入我的应用程序的好方法,那么也请告诉我。谢谢!

【问题讨论】:

  • “当我将 aar 导入一个单独的应用程序项目时”——您可能希望提供更多关于您在此处所做的事情的细节。 “这个“libhello-jni.so”文件到底是什么? -- 那是一个 Linux .so 文件,将 C/C++ 代码编译到共享库的结果。 “我为什么需要它?” -- 你编写了 C/C++ 并试图执行它。 “我能够以 apk 的形式完美运行它”——您的 APK 文件包含 .so。您的 AAR 也应该如此,这就是为什么您可能希望详细解释您是如何创建 AAR 以及如何尝试使用它的原因。
  • 谢谢!我添加了有关如何将 aar 文件作为库添加到我的应用程序中的说明。
  • AAR 是 ZIP 样式的存档。查看您的内部文件,看看您是否有 .so 文件。如果答案是“否”,那么问题在于 AAR 是如何创建的,我猜。如果答案是“是”,您可能需要切换到使用工件存储库而不是那个我从未尝试过的导入选项。我已经使用 NDK 编译的库(例如,CWAC-AndDown)成功发布了 AAR,所以我知道这是可能的。
  • 再次感谢您的快速回复。我通过在 aar 项目目录的终端中键入“gradle assembleDebug”来构建 aar 文件。如何查看 aar 文件? (我在 Mac 上)
  • "如何查看 aar 文件的内部?" -- 与查看任何 ZIP 存档的方式相同。我假设 OS X 有 unzip 或等效工具。

标签: android android-ndk java-native-interface aar


【解决方案1】:

原来我必须在我的 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”。

【讨论】:

  • 这并没有解释您如何从 AAR 中引用 .so 文件。这一步也可以在你的 android.mk LOCAL_MODULE 标签中完成。
【解决方案2】:

您必须使用来自 Android NDK 的命令 ndk-build 构建本机代码。

此过程将生成 linhello-jni.so,它将包含在您的构建中。

【讨论】:

  • 你能告诉我如何运行 ndk-build 命令吗?这就是我得到的:
  • $ ndk-build Android NDK: 找不到应用程序项目目录! Android NDK:请定义 NDK_PROJECT_PATH 变量指向它。
猜你喜欢
  • 2021-10-14
  • 2017-03-09
  • 2017-03-03
  • 2011-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-10
相关资源
最近更新 更多