【问题标题】:Android Studio - App + NDK Module libraryAndroid Studio - 应用 + NDK 模块库
【发布时间】:2015-12-30 11:47:53
【问题描述】:

在花了好几个小时寻找我的问题的解决方案并浏览了各种论坛(包括这个论坛)后,我终于决定问我的问题,希望其他地方还没有完全回答。

我正在尝试构建一个非常复杂的架构:

  • 我有 C 源代码,我在单独的静态库中编译 (.a)
  • 我通过模块库中的 JNI 使用它们
  • 我想在应用项目中使用这个库。

我首先成功完成了以下测试 - 我已经设法在没有 NDK 的情况下制作了一个模块库并使用该应用程序编译它。 - 我还设法直接在应用程序中使用静态库和 JNI,但是

我在以下步骤中失败了: - 模块内部的JNI和调用模块类的app组合不起作用。

我认为问题在于 aar 的包含,因为当 aar 在库构建/输出目录中时,我在应用程序的构建目录中找不到爆炸的 aar。此外,之前的所有测试(包括使用 JNI 成功)。

我没有使用实验模型,因为它是实验性的,并且静态库存在已知限制。

我的项目结构是:

- App
    - src
        - main
            - java
                - activity  
- bar
    - src
        - main
            - java
                - class
            - jni
                - include
                    - *.h
                - libs
                    - abis...
                        - libmod1.a
                        - libmod2.a
                Android.mk
                Application.mk
                bar.c
                bar.h

应用程序 build.gradle 如下所示:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.0"

    defaultConfig {
        applicationId "com.test.foo"
        minSdkVersion 10
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }

    buildTypes {

        release {
            debuggable          false
            jniDebuggable       false
            minifyEnabled       false
        }
        unsigned {
            debuggable          false
            jniDebuggable       false
            minifyEnabled       false
        }
        debug {
            debuggable          true
            jniDebuggable       true
            minifyEnabled       false
        }
    }


    productFlavors {
        x86 {
            ndk {
                abiFilter "x86"
            }
        }
        mips {
            ndk {
                abiFilter "mips"
            }
        }
        armv7 {
            ndk {
                abiFilter "armeabi-v7a"
            }
        }
        arm {
            ndk {
                abiFilter "armeabi"
            }
        }
        fat
    }

    project.ext.versionCodes = ['armeabi':1, 'armeabi-v7a':2, 'arm64-v8a':3, 'mips':5, 'mips64':6, 'x86':8, 'x86_64':9]

    android.applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.versionCodeOverride =
                    project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + defaultConfig.versionCode
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    compile project( ":bar" )
}

模块 build.gradle 如下所示:

apply plugin: 'com.android.library'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.0"

    defaultConfig {
        minSdkVersion 10
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"

        ndk {
            moduleName "module"
        }
    }
    buildTypes {

        release {
            debuggable      false
            jniDebuggable   false
            minifyEnabled   false
        }
        unsigned {
            debuggable      false
            jniDebuggable   false
            minifyEnabled   false
        }
        debug {
            debuggable      true
            jniDebuggable   true
            minifyEnabled   false
        }
    }

    productFlavors {
        x86 {
            ndk {
                abiFilter "x86"
            }
        }
        mips {
            ndk {
                abiFilter "mips"
            }
        }
        armv7 {
            ndk {
                abiFilter "armeabi-v7a"
            }
        }
        arm {
            ndk {
                abiFilter "armeabi"
            }
        }
        fat
    }
    sourceSets.main {
        jniLibs.srcDir 'src/main/libs'
        jni.srcDirs     = []
    }

    task ndkBuild(type: Exec) {
        commandLine android.ndkDirectory.getAbsolutePath()+'/ndk-build', '-C', file('src/main').absolutePath
    }

    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn ndkBuild
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

模块 jni 目录中的我的 Android.mk 是: LOCAL_PATH:= $(调用我的目录)

#### Mod1
include $(CLEAR_VARS)
LOCAL_MODULE            := mod1
LOCAL_SRC_FILES         := libs/$(TARGET_ARCH_ABI)/libmod1.a
include $(PREBUILT_STATIC_LIBRARY)

#### Mod2
include $(CLEAR_VARS)
LOCAL_MODULE            := pxnav
LOCAL_SRC_FILES         := libs/$(TARGET_ARCH_ABI)/libmod2.a
LOCAL_STATIC_LIBRARIES  := pxfd
include $(PREBUILT_STATIC_LIBRARY)

##### Parser
include $(CLEAR_VARS)
LOCAL_MODULE            := module
LOCAL_C_INCLUDES        := $(LOCAL_PATH)/include
LOCAL_LDLIBS            += -landroid -llog
LOCAL_SRC_FILES         := bar.c
LOCAL_STATIC_LIBRARIES  := mod1 mod2
include $(BUILD_SHARED_LIBRARY)

【问题讨论】:

  • 我补充说,如果我直接使用生成的 aar:新模块 > 导入 .jar/.aar 它也可以完美运行。我不希望每次编译时都必须将 aar 复制到指定目录。

标签: android c module android-ndk static-libraries


【解决方案1】:

我为类似任务找到了一个简单的解决方法:我只是为 app 模块设置了jniLibs.srcDir。现在我不依赖于分解 aar 来获得 .so 文件。顺便说一句,当您决定切换到 experimental 插件(以使用本机调试、C++ 语法高亮和交叉引用和其他细节)时,请您检查 define LOCAL_SRC_FILES in ndk{} DSL .

【讨论】:

  • 我不明白它有什么帮助。您将应用程序内的 jniLibs.srcDir 设置为模块内的 libs 目录?在那种情况下,您如何设法让应用程序看到 aar 中的类?我的问题是,即使是 bar 模块库中的类在应用程序中也无法使用。
  • 我尝试了您的解决方案,我确实在我的 APK 中链接了库,但是 APK 中仍然缺少 AAR 的类,并且无法在应用程序中实例化。
  • 该库不构建其本机代码;它伪装成一个纯 Java 模块。你说你在一个初步实验中成功地使用了一个库,是吗?
  • 哦,我明白了。您建议不应在 AAR 中编译 NDK 代码,而是在 APK 中编译,我会链接一个无 NDK 的 AAR 吗?好吧,我想它可以工作,但我宁愿拥有一个完全功能的 AAR(如果我将 AAR 作为模块导入,它就可以工作)。
  • 你的意思是,只要库是外部 Module,它就可以工作;但是如果你有这个库 ProjectModule 部分,并且这个 Module 涉及本机代码,那么 gradle 插件不能正确处理爆炸的 AAR?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-16
  • 2016-04-15
  • 1970-01-01
  • 1970-01-01
  • 2017-01-23
相关资源
最近更新 更多