使用NDK包括预编译的静态库

时间:2014-12-17 18:10:06

标签: android android-ndk android-studio

我希望包含一个在我的Android Studio NDK项目中预编译的静态库。我正在使用Android Studio 1.0.1,任何在SO上尝试此问题的解决方案似乎已过时(或涉及创建库项目并包含它)。

结构如下:

app
/--src
/--main
/--java
+--jni
+--jniLibs
   /--armeabi
       /--libpng.a
    --armeabiv7
       /--libpng.a
    ...(for each abi)

我正在尝试包含库libpng。我尝试创建jniLibs(根据ph0b(很棒的指南,顺便说一句)并将libpng.a添加到相应的ABI文件夹。这仍然给我错误 - 找不到-llibpng 当我尝试使用以下代码进行编译:

ndk {
        moduleName "game" 
        cFlags "-std=c++11 -fexceptions -DANDROID -I${project.buildDir}/../src/main/jni/include \
                -I${project.buildDir}/../src/main/jni/include/png"
        ldLibs "EGL", "GLESv3", "dl", "log", "android", "libpng"
        stl "gnustl_static"
}

5 个答案:

答案 0 :(得分:3)

现在可以通过实验性插件正常工作。

有关完整说明,请参阅this whole excellent article,这是我从中获取此信息的地方,但我也是自己使用它并且有效。

这是我的build.gradle - 请注意,就我而言,它适用于图书馆项目,而且我使用静态链接而不是共享。

buildscript {
    dependencies
            {
                classpath "com.android.tools.build:gradle-experimental:0.7.0-alpha3"
            }
}
apply plugin: 'com.android.model.library'

model {
    repositories {
        libs(PrebuiltLibraries) {
            v8_base {
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("src/main/jni/libs/${targetPlatform.getName()}/libv8_base.a")
                }
            }
            v8_libbase {
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("src/main/jni/libs/${targetPlatform.getName()}/libv8_libbase.a")
                }
            }
            v8_libplatform {
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("src/main/jni/libs/${targetPlatform.getName()}/libv8_libplatform.a")
                }
            }
            v8_nosnapshot {
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("src/main/jni/libs/${targetPlatform.getName()}/libv8_nosnapshot.a")
                }
            }
        }
    }

    android {

        compileSdkVersion 23
        buildToolsVersion "23.0.2"

        sources {
            main {
                jni {
                    source {
                        srcDir "src/main/jni"
                    }
                    dependencies {
                        library "v8_base" linkage "static"
                        library "v8_libbase" linkage "static"
                        library "v8_libplatform" linkage "static"
                        library "v8_nosnapshot" linkage "static"
                    }
                }
            }
        }

        ndk {
            moduleName "v8example"
            cppFlags.add("-std=c++11")
            cppFlags.add("-I${file("src/main/jni/include")}".toString())
            cppFlags.add("-fexceptions")
            ldLibs.add("log")
            stl "stlport_static"
            abiFilters.add("armeabi armeabi-v7a x86")
        }
    }
}

另一种方法是使用旧的Gradle方法自行调用ndkBuild,从而使用.mk文件。这也很好,但你失去了与Android Studio的良好集成,例如您的jni文件正确显示。

答案 1 :(得分:1)

在Android Studio 1.0.2中添加.so库

  1. 在“src / main /”
  2. 中创建文件夹“jniLibs”
  3. 将所有.so库放在“src / main / jniLibs”文件夹
  4. 文件夹结构看起来像,
    | --app:
    | - | --src:
    | - | - | - 主
    | - | - | - | --jniLibs
    | - | - | - | - | --armeabi
    | - | - | - | - | - | - 。so文件
  5. 没有额外的代码只需同步您的项目并运行您的应用程序。

    参考
    https://github.com/commonsguy/sqlcipher-gradle/tree/master/src/main

答案 2 :(得分:1)

由于ndk支持现在限制在gradle中,你可以尝试使用不同abi的静态库。

    ndk {
        moduleName "game" 
        ....
        ldLibs ..., file(projectDir).absolutePath+"/src/main/jniLibs/\$(TARGET_ARCH_ABI)/libpng.a"
        ....
    }

答案 3 :(得分:1)

你不能只包含.so文件,你还需要有src文件夹,它们实际上提供了访问那些.so文件中的方法的接口。我建议不要将你的项目与图书馆联系起来。

最好的方法是将它作为android studio中的库模块包含在内,并丢弃jni文件夹以禁用ndkbuild,并通过在build.gradle文件中添加以下内容将jnilib指向/ libs文件夹

jni.srcDirs = [] //disable automatic ndk-build call
jniLibs.srcDirs = [ 'libs' ] //no need to copy the .so files from /libs to /jniLibs folder

(检查libs目录是否已由android studio与.so文件正确导入)

将库导入为模块会自动执行以下操作

  

a)项目文件夹中的 yourlibrary 库文件夹,并根据gradle约定重新构建   b)导入项目(在settings.gradle中包含': yourlibrary ')和
  c)创建依赖项(“文件 - >项目结构 - >从左侧子窗口中选择主应用程序模块 - >依赖项(最后一个选项卡) - >按右侧的绿色”+“ - > yourlibrary 作为模块依赖 - > OK“)

答案 4 :(得分:0)

这真的很难看,但它确实有效!您可以欺骗Gradle,允许您将代码注入生成的Android.mk文件中:

    ndk {
        abiFilter "armeabi-v7a"

        // We need to inject the static library into the
        // NDK build, and Gradle doesn't offer a way to directly
        // modify the Android.mk file... So we hack it!
        //
        // You can see the end result at:
        //   build/intermediates/ndk/debug/Android.mk

        moduleName "This_is_a_terrible_Gradle_hack\n" +

        "include \$(CLEAR_VARS)\n" +

        "LOCAL_MODULE := mystaticlib_prebuilt\n" +
        "LOCAL_EXPORT_C_INCLUDES := mystaticlib/include\n" +
        "LOCAL_SRC_FILES := mystaticlib/libmystaticlib.a\n" +

        "include \$(PREBUILT_STATIC_LIBRARY)\n" +

        "include \$(CLEAR_VARS)\n" +
        "LOCAL_MODULE := MyActualModule\n" +
        "LOCAL_STATIC_LIBRARIES += mystaticlib_prebuilt"

        cFlags "-std=c++11 -fexceptions -frtti -pthread"
        stl "gnustl_shared"
        ldLibs "log", "OpenSLES", "z"
    }