如何使用 gradle 以编程方式将 libc++_shared.so 包含到我的 APK 中?

Posted

技术标签:

【中文标题】如何使用 gradle 以编程方式将 libc++_shared.so 包含到我的 APK 中?【英文标题】:How to include libc++_shared.so into my APK programmatically with gradle? 【发布时间】:2021-02-14 20:16:33 【问题描述】:

在项目中更新:

Gstreamer 1.14.5 -> Gstreamer 1.18.0

NDKr16 -> NDKr21.3.6528147

build:gradle:3.5.3 -> build:gradle:4.1.0

buildToolsVersion 29.0.3

 compileSdk: 29,
 minSdk    : 26,
 targetSdk : 29,
 material  : "1.2.1",
 constraint: "2.0.2",
 ktx       : "1.1.0",
 espresso  : "3.1.0",
 mockito   : "2.9.0",
 junit     : "4.13.1"

此更新产生一个问题:

java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found
    at java.lang.Runtime.loadLibrary0(Runtime.java:1071)
    at java.lang.Runtime.loadLibrary0(Runtime.java:1007)
    at java.lang.System.loadLibrary(System.java:1667)
    at com.kbnt.naparnik.client.MainActivity.<clinit>(MainActivity.java:103)
    at java.lang.Class.newInstance(Native Method) 
...

项目构建正确,但是当我运行应用程序时它会因问题而崩溃

android.mk 文件:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := client
LOCAL_SRC_FILES := client.c
LOCAL_SHARED_LIBRARIES := gstreamer_android
LOCAL_LDLIBS := -llog -landroid
include $(BUILD_SHARED_LIBRARY)

ifndef GSTREAMER_ROOT_ANDROID
    $(error GSTREAMER_ROOT_ANDROID is not defined!)
endif
ifeq ($(TARGET_ARCH_ABI),armeabi)
    GSTREAMER_ROOT        := $(GSTREAMER_ROOT_ANDROID)/arm
else ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
    GSTREAMER_ROOT        := $(GSTREAMER_ROOT_ANDROID)/armv7
else ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
    GSTREAMER_ROOT        := $(GSTREAMER_ROOT_ANDROID)/arm64
else ifeq ($(TARGET_ARCH_ABI),x86)
    GSTREAMER_ROOT        := $(GSTREAMER_ROOT_ANDROID)/x86
else ifeq ($(TARGET_ARCH_ABI),x86_64)
    GSTREAMER_ROOT        := $(GSTREAMER_ROOT_ANDROID)/x86_64
else
    #$(error Target arch ABI not supported: $(TARGET_ARCH_ABI))
    GSTREAMER_ROOT        := $(GSTREAMER_ROOT_ANDROID)/armv7
endif

GSTREAMER_NDK_BUILD_PATH  := $(GSTREAMER_ROOT)/share/gst-android/ndk-build/
include $(GSTREAMER_NDK_BUILD_PATH)/plugins.mk

GSTREAMER_PLUGINS         :=  $(GSTREAMER_PLUGINS_CORE)         \
                             $(GSTREAMER_PLUGINS_CODECS)        \
                             $(GSTREAMER_PLUGINS_EFFECTS)       \
                             $(GSTREAMER_PLUGINS_NET)           \
                             $(GSTREAMER_PLUGINS_CAPTURE)       \
                             $(GSTREAMER_PLUGINS_PLAYBACK)      \
                             $(GSTREAMER_PLUGINS_SYS)

GSTREAMER_EXTRA_DEPS      := gstreamer-video-1.0
include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer-1.0.mk

Application.mk 文件:

APP_STL := c++_shared
APP_PLATFORM := android-26

我在文档https://developer.android.com/ndk/guides/cpp-support#c_runtime_libraries 中找到了注释:

libc++ 不是系统库。如果您使用 libc++_shared.so,它必须包含在您的 APK 中。如果您使用 Gradle 构建应用程序,则会自动处理。

我了解它构建不正确,因为我的 APK 不包含库

项目结构

app/build.gradle:

android 
compileSdkVersion versions.compileSdk
defaultConfig 
    ...
    externalNativeBuild 
        ndkBuild 
            if (System.getenv("GSTREAMER_ROOT_ANDROID") == null)
                throw new GradleException("Define GSTREAMER_ROOT_ANDROID environment variable")
            targets "client"
            abiFilters "armeabi-v7a", 'arm64-v8a'
        
    

buildTypes 
    release 
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    

externalNativeBuild 
    ndkBuild 
        path 'src/main/jni/Android.mk'
    

ndkVersion '21.3.6528147'
buildToolsVersion '29.0.3'
...

【问题讨论】:

externalNativeBuild.ndkBuild 部分在app/build.gradle 中的外观如何? @NikolayKhilyuk 将 app/build.gradle 添加到问题中 一切似乎都很好,当然,如果路径正确(src/main/jni/Android.mk),因为它与项目结构的快照不同。 @NikolayKhilyuk 路径是正确的。更新了一个项目结构截图 【参考方案1】:

我重构了我的 Android.mk GSTREAMER_PLUGINS 字段并添加了 GSTREAMER_EXTRA_LIBS。我用项目中使用的特定插件替换了类别,它解决了我的问题。

...
GSTREAMER_PLUGINS   := coreelements udp rtpmanager rtp opengl playback
GSTREAMER_EXTRA_LIBS    := -liconv
...

分类中的某些插件似乎有错误

感谢@NikolayKhilyuk 试图帮助我

【讨论】:

【参考方案2】:

看起来像targets "client" 问题。尝试完全删除它或指定NDK_APPLICATION_MK

...
    externalNativeBuild 
        ndkBuild 
            ...
            targets "client"
            arguments "NDK_APPLICATION_MK:=Application.mk"
            ...
        
    


...

【讨论】:

1) 如果我删除 targets "client",请处理此问题:任务“:app:externalNativeBuildDebug”执行失败。 > 目标 gstreamer_android 的 gst-build-arm64-v8a/libgstreamer_android.so 中的预期输出文件,但没有这是解决方案,上面写着 put targets field link 2) 如果设置arguments "NDK_APPLICATION_MK:=Application.mk" 它会产生另一个问题:任务':app:generateJsonModelDebug'的执行失败。 > 为 ndkBuild /home/dev18/Development/naparnik-client/app/src/main/jni/Android.mk 执行外部原生构建 可能路径有问题,试试arguments "NDK_APPLICATION_MK:=src/main/jni/Application.mk"

以上是关于如何使用 gradle 以编程方式将 libc++_shared.so 包含到我的 APK 中?的主要内容,如果未能解决你的问题,请参考以下文章

Gradle:如何在java中以编程方式声明对项目特定配置的依赖关系

有没有办法以编程方式列出所有 gradle 依赖项?

如何以编程方式查找已加载共享库的版本?

有没有办法以编程方式列出所有gradle依赖项?

libc中的错误?如何读取转储文件?

滚动视图错误以编程方式自动布局