【问题标题】:How can I Invoke a function/method from a .so file in Android studio如何从 Android Studio 中的 .so 文件调用函数/方法
【发布时间】:2018-10-17 02:02:16
【问题描述】:

我正在尝试在我的 Android 应用中实现 ffmpeg。 我已经有了我需要的预建 .so 文件。

我只是不知道如何调用库中的众多函数之一。 到目前为止,这是我所拥有的:

我已将每个 .so 文件放在 jniLibs 文件夹下

这是我的 gradle 文件

从那里,我像这样加载库:

static {
    Log.e("jni", "starting");
    System.loadLibrary("avdevice");
    Log.e("jni", "finished");
}

加载成功。到目前为止,一切都很好。

接下来,我查看 .h 文件以查找可以调用的方法。请注意,我假设这个 .h 文件被捆绑到 .so 文件中。这可能就是一切崩溃的地方。

/**
* Return the LIBAVDEVICE_VERSION_INT constant.
*/

unsigned avdevice_version(void);

因为我现在知道我需要调用的方法名,所以我把它放在我的代码中:

public native int avdeviceVersion();

当我尝试拨打 avdeviceVersion(); 时,我收到了这条错误消息:

java.lang.UnsatisfiedLinkError: No implementation found for int com.my.app.ApplicationContext.avdeviceVersion() (tried Java_com_my_app_ApplicationContext_avdeviceVersion and Java_com_my_app_ApplicationContext_avdeviceVersion__)

现在,我意识到 Java_com_my_app_ApplicationContext_avdeviceVersion 与 .h 文件中的方法名称不匹配。但是,我不知道如何使它匹配以及下一步该做什么。如果您知道,请尽可能详细地解释它。假设我什么都不知道:)

更新

我添加了 Android.mk 文件以及 Application.mk,我还添加了一个名为 video.c 的 Jni 桥。

JNIEXPORT jint JNICALL Java_com_my_app_jni_VideoKit_version(JNIEnv *env, jobject instance, jobjectArray args) {
return (*env)->avdevice_version();}

我的 Android.mk 是这样的:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := avdevice
LOCAL_SRC_FILES := video.c
include $(BUILD_SHARED_LIBRARY)

有了这些改变,结果是一样的。

【问题讨论】:

  • 那么您是否在 C 端调用没有包装器的 .so 库方法来处理 JNI 桥接器?
  • @MorrisonChang 嘿,我觉得这是我出错的地方。你能进一步解释你的意思吗?我所做的只是将 ffmpeg 编译成 .so 文件。我需要用包装器更新 ffmpeg 库吗?
  • 我会用一个简单的“hello world JNI”示例确认您的设置/配置是否正确,然后查看您的库是否符合 JNI。我的猜测是您缺少“桥代码”,即从 Java double 到 C/C++ double 等,这在所有 JNI 教程中都有介绍,但我可能弄错了。

标签: android android-studio android-ndk java-native-interface .so


【解决方案1】:

您应该配置使用 c/c++ 类的环境。 您需要 CMakeLists.txt 或 Android.mk / Application.mk。

那么,你应该创建一个类来链接java类和native类。

This link 可以帮到你。

正如错误消息所说, 需要jint Java_{PACKAGE_NAME}_{CLASS_NAME}_{FUNCTION_NAME}(JNIEnv *env, jobject obj)。你可以在函数内部调用avdevice_version()

更新

在Android.mk中,先制作预建共享库,再制作链接共享库

include $(CLEAR_VARS)
LOCAL_MODULE := static_avdevice # you can change the name
LOCAL_SRC_FILES = avdevice.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include # header file directory
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include # header file directory
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := jniLinker
LOCAL_SRC_FILES := video.c
LOCAL_STATIC_LIBRARIES := static_avdevice
include $(BUILD_SHARED_LIBRARY)

然后,加载库。 System.loadLibrary("jniLinker");

而且,googlesamples github 中有很多示例。 https://github.com/googlesamples/android-ndk/tree/master/hello-libs 这是使用 3rd-party 库的代码示例。 (但它使用 CMake。)

【讨论】:

  • 今晚我会试试这个。明天我会告诉你发生了什么。谢谢!
  • @ss.techie 我采纳了你的建议。请参阅原帖上的“更新”。这是你想要的吗?
猜你喜欢
  • 1970-01-01
  • 2020-05-07
  • 2016-04-14
  • 1970-01-01
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多