【问题标题】:Android studio, gradle and NDKAndroid Studio、Gradle 和 NDK
【发布时间】:2013-05-16 02:18:33
【问题描述】:

我对整个 gradle 和 Android Studio 支持非常陌生。我已经设法使用导出选项将我的 android 项目转换为 gradle。

但我正在寻找一些文档或起点如何将 NDK 构建集成到 gradle 构建过程中。

如果可能的话,我还需要某种“之后”阶段,将构建二进制文件(.so 文件)复制到资产目录。

【问题讨论】:

标签: android android-ndk gradle android-studio


【解决方案1】:

我们已经发布了集成的第一个版本作为 1.3 中的预览版:http://tools.android.com/tech-docs/android-ndk-preview

即使在 1.3 成为最终版本后,集成仍将保持预览状态。目前没有关于何时最终确定的预计到达时间(截至 2015 年 7 月 10 日)。

更多信息在这里:http://tools.android.com/tech-docs/android-ndk-preview

【讨论】:

  • 如果我可以在 Android Studio 下使用 NDK 和命令完成进行调试(以及 Gradle 支持),那就太好了
  • @GREnvoy - 我们如何在 Android Studio 中配置正确的 NDK 构建器?你能给我步骤吗? :)
  • @DirtyBeach 为什么它已经过时了? Studio 中仍然没有集成 NDK。我们正在努力,但目前没有预计到达时间。
  • 我的行动是基于我对“整合”的定义。我理解它的意思是“一种将 NDK 与 gradle 一起使用的方法”,它现在确实存在,尽管它们都不是很好的解决方案。但是,根据您的评论,您的团队似乎对真正的集成还有其他想法。我收回我之前的声明。
  • NDK 集成是在 Google IO 2015 期间宣布的。它在 Android Studio 1.3 中可用(预览版可以很快下载。我会在可用时发布链接)。
【解决方案2】:

更新:支持 NDK 的 Android Studio 现已推出:http://tools.android.com/tech-docs/android-ndk-preview

对于使用脚本构建,下面的 gradle 解决方案应该可以工作:

我正在使用我的构建脚本并添加到我的文件中(似乎适用于0.8+):这似乎等同于以下解决方案(但在 gradle 文件中看起来更好):

 android {
    sourceSets {
        main {
            jniLibs.srcDirs = ['native-libs']
            jni.srcDirs = [] //disable automatic ndk-build
        }
    }
 }

不幸的是,如果目录不存在或不包含.so 文件,则构建不会失败。

【讨论】:

  • 这不再适用于新的 Android Studio 版本,解决方法?
  • @powder366 看我的回答。
  • 一点 Groovy 魔法:tasks.withType(com.android.build.gradle.tasks.PackageApplication) { it.jniFolders = [file("libs")] as Set }。谢谢大家的帮助!
  • android Studio 0.8.9的程序是什么
  • @plaisthos 非常感谢您指出正确的方向! gradle 脚本中的第二行 jni.srcDirs = [] //disable automatic ndk-build 非常重要,因为它会阻止 Android Studio 重新构建 C/C++ 源代码。我一直试图解决这个问题两天,直到我看到你的帖子,这解决了我的问题。我真的认为 NDK 构建最好仅由 Android.mk 命令行 makefile 单独构建,而不是由 gradle 脚本构建,因为 Makefile 已经构建了 40 多年的 C/C++!
【解决方案3】:

随着 Android Studio 更新到 1.0,NDK 工具链支持得到了极大的改进(注意:请阅读本文底部的更新,以了解新的实验性 Gradle 插件和 Android Studio 1.5 的使用情况)。

Android Studio 和 NDK 集成得很好,因此您只需在模块的 build.gradle 中创建一个 ndk{} 块,并将源文件设置到 (module)/src/main/jni 目录 - 和你完成了!

不再需要从命令行进行 ndk-build。

我已经在我的博文中写了所有关于它的内容:http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/

重点是:

这里有两件事你需要知道。默认情况下,如果您希望将外部库加载到 Android 应用程序中,则默认情况下会在 (module)/src/main/jniLibs 中查找它们。您可以通过在模块的 build.gradle 中设置 sourceSets.main.jniLibs.srcDirs 来更改此设置。您需要一个子目录,其中包含您所针对的每个架构的库(例如 x86、arm、mips、arm64-v8a 等……)

您希望通过 NDK 工具链默认编译的代码将位于 (module)/src/main/jni 和上面类似,您可以通过在模块的 sourceSets.main.jni.srcDirs 中设置来更改它build.gradle

并将其放入模块的 build.gradle 中:

ndk {
  moduleName "SeePlusPlus" // Name of C++ module (i.e. libSeePlusPlus)
  cFlags "-std=c++11 -fexceptions" // Add provisions to allow C++11 functionality
  stl "gnustl_shared" // Which STL library to use: gnustl or stlport
}

这是编译你的 C++ 代码的过程,你需要从那里加载它,并创建包装器 - 但从你的问题来看,你已经知道如何做所有这些,所以我不会重新散列。

另外,我在此处放置了此示例的 Github 存储库:http://github.com/sureshjoshi/android-ndk-swig-example

更新日期:2015 年 6 月 14 日

当 Android Studio 1.3 出来时,应该会通过 JetBrains CLion 插件对 C++ 提供更好的支持。我目前假设这将允许在 Android Studio 内进行 Java 和 C++ 开发;但是我认为我们仍然需要使用 Gradle NDK 部分,如上所述。此外,我认为仍然需要编写 JavaC++ 包装文件,除非 CLion 会自动执行这些操作。

更新日期:2016 年 1 月 5 日

我已更新我的博客和 Github 存储库(在开发分支中)以使用带有最新实验性 Gradle 插件 (0.6.0-alpha3) 的 Android Studio 1.5。

http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/ http://github.com/sureshjoshi/android-ndk-swig-example

NDK 部分的 Gradle 构建现在如下所示:

android.ndk {
    moduleName = "SeePlusPlus" // Name of C++ module (i.e. libSeePlusPlus)
    cppFlags.add("-std=c++11") // Add provisions to allow C++11 functionality
    cppFlags.add("-fexceptions")
    stl = "gnustl_shared" // Which STL library to use: gnustl or stlport
}

此外,非常棒的是,Android Studio 使用“native”关键字自动完成 C++-Java 生成的包装器:

然而,它并不完全乐观......如果你使用 SWIG 包装一个库来自动生成代码,然后尝试使用 native 关键字自动生成,它会将代码放在错误的位置你的 Swig _wrap.cxx 文件...所以你需要将它移动到“extern C”块中:

更新日期:2017 年 10 月 15 日

如果我没有提到 Android Studio 2.2 及更高版本通过 Gradle 和 CMake 对 NDK 工具链具有本质上的“本机”(无双关语)支持,那将是我的疏忽。现在,当您创建一个新项目时,只需选择 C++ 支持就可以了。

您仍然需要生成自己的 JNI 层代码,或者使用我上面提到的 SWIG 技术,但现在在 Android 项目中搭建 C++ 的脚手架是微不足道的。

Android Studio 将获取 CMakeLists 文件(放置 C++ 源文件的位置)中的更改,并自动重新编译任何关联的库。

【讨论】:

  • 把*.so放到(module)/src/main/jniLibs中
  • 为什么在使用 Android Studio 时总是设置 NDEBUG,即使在调试版本中也是如此
【解决方案4】:

在 Google IO 2015 中,Google 宣布在 Android Studio 1.3 中全面集成 NDK。

它现在不再预览,可供所有人使用:https://developer.android.com/studio/projects/add-native-code.html

旧答案:如果您的项目源中有 jni 目录,Gradle 会自动调用 ndk-build

这适用于 Android Studio 0.5.9(金丝雀版本)。

  1. Download the NDK

  2. ANDROID_NDK_HOME 添加到您的环境变量或将ndk.dir=/path/to/ndk 添加到您的Android Studio 项目中的local.properties。这允许 Android Studio 自动运行 ndk。

  3. 下载 latest gradle sample projects 以查看 ndk 项目的示例。 (它们位于页面底部)。一个好的示例项目是ndkJniLib

  4. 从 NDK 示例项目中复制 gradle.build。它看起来像这样。这个gradle.build 为每个架构创建了一个不同的 apk。您必须使用build variants 窗格选择您想要的架构。

    apply plugin: 'android'
    
    dependencies {
        compile project(':lib')
    }
    
    android {
        compileSdkVersion 19
        buildToolsVersion "19.0.2"
    
        // This actual the app version code. Giving ourselves 100,000 values [0, 99999]
        defaultConfig.versionCode = 123
    
        flavorDimensions "api", "abi"
    
        productFlavors {
            gingerbread {
                flavorDimension "api"
                minSdkVersion 10
                versionCode = 1
            }
            icecreamSandwich {
                flavorDimension "api"
                minSdkVersion 14
                versionCode = 2
            }
            x86 {
                flavorDimension "abi"
                ndk {
                    abiFilter "x86"
                }
                // this is the flavor part of the version code.
                // It must be higher than the arm one for devices supporting
                // both, as x86 is preferred.
                versionCode = 3
            }
            arm {
                flavorDimension "abi"
                ndk {
                    abiFilter "armeabi-v7a"
                }
                versionCode = 2
            }
            mips {
                flavorDimension "abi"
                ndk {
                    abiFilter "mips"
                }
                versionCode = 1
            }
            fat {
                flavorDimension "abi"
                // fat binary, lowest version code to be
                // the last option
                versionCode = 0
            }
        }
    
        // make per-variant version code
        applicationVariants.all { variant ->
            // get the version code of each flavor
            def apiVersion = variant.productFlavors.get(0).versionCode
            def abiVersion = variant.productFlavors.get(1).versionCode
    
            // set the composite code
            variant.mergedFlavor.versionCode = apiVersion * 1000000 + abiVersion * 100000 + defaultConfig.versionCode
        }
    
    }
    

请注意,这将忽略您的 Android.mk 和 Application.mk 文件。作为一种解决方法,您可以告诉 gradle 禁用自动 ndk-build 调用,然后手动指定 ndk 源的目录。

sourceSets.main {
    jniLibs.srcDir 'src/main/libs' // use the jni .so compiled from the manual ndk-build command
    jni.srcDirs = [] //disable automatic ndk-build call
}

此外,您可能希望在 gradle 构建脚本中显式调用 ndk-build,因为您刚刚禁用了自动调用。

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

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

【讨论】:

  • 是的。但这仅适用于 Unix 平台,并且如果您使用比非常简单的 ndk 配置/makefile 更复杂的情况,也会受到限制。
  • 是的,它会为您可以在 gradle 构建文件中设置的有限内容自动生成 makefile,但是有一种解决方法。我将其添加到我的答案中。
  • 对 ndk-build 的调用只能在命令行中起作用,而不能在 Android Studio 中起作用。
  • 虽然这不是最新的答案,但它似乎可能是最准确的。特别注意第 3 步:“下载 最新的 gradle 示例项目”。
  • 我使用这个 hack 而不是禁用 src 目录,这样我就可以在 ide tasks.all { task -> if (task.name.contains('Ndk')) task.enabled = false } 中编辑 c/c++ 文件
【解决方案5】:

我发现“gradle 1.11 com.android.tools.build:gradle:0.9.+”现在支持 pre-build ndk,你可以把 *.so 放在 dir src/main/jniLibs 中。 在构建 gradle 时会将 ndk 打包到正确的位置。

这是我的项目

项目: |--src |--|--主要 |--|--|--java |--|--|--jniLibs |--|--|--|--armeabi |--|--|--|--|--.so 文件 |--库 |--|--other.jar

【讨论】:

    【解决方案6】:

    正如 Xavier 所说,如果你使用 gradle 0.7.2+,你可以将你的预编译放在 /src/main/jniLibs/ 中

    取自:https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/ctDp9viWaxoJ

    【讨论】:

    • 如何查看 0.7.2 ndkJniLib 中提到的示例?
    • 对使用SqlCipher等库很有用
    【解决方案7】:

    到目前为止(Android Studio v0.8.6)它非常简单。以下是创建“Hello world”类型应用的步骤:

    1. 下载 Android NDK 并将根文件夹放在合理的位置 - 可能与 SDK 文件夹位于同一位置。

    2. 将以下内容添加到您的 local.properties 文件中: ndk.dir=<path-to-ndk>

    3. 将以下内容添加到 defaultConfig 闭包内的 build.gradle 文件中,就在 versionName 行之后:ndk { moduleName="hello-world" }

    4. 在您的应用模块的main 目录中,创建一个名为jni 的新文件夹。

    5. 在该文件夹中,创建一个名为 hello-world.c 的文件,如下所示。

    6. 请参阅下面的示例 Activity 代码,了解如何调用 hello-world.c 中的方法(或者它是函数?)的示例。


    hello-world.c

    #include <string.h>
    #include <jni.h>
    
    jstring
    Java_me_mattlogan_ndktest_MainActivity_stringFromJNI(JNIEnv* env, jobject thiz)
    {
        return (*env)->NewStringUTF(env, "Hello world!");
    }
    

    MainActivity.java

    public class MainActivity extends Activity {
    
        static {
            System.loadLibrary("hello-world");
        }
    
        public native String stringFromJNI();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            String testString = stringFromJNI();
    
            TextView mainText = (TextView) findViewById(R.id.main_text);
            mainText.setText(testString);
        }
    }
    

    build.gradle

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 20
        buildToolsVersion "20.0.0"
    
        defaultConfig {
            applicationId "me.mattlogan.ndktest"
            minSdkVersion 15
            targetSdkVersion 20
            versionCode 1
            versionName "1.0"
    
            ndk {
                moduleName "hello-world"
            }
        }
        buildTypes {
            release {
                runProguard false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
    }
    

    Find the full source code of a very similar app here (minus the NDK).

    【讨论】:

    • 我正在按照我当前项目中的指示进行操作,但是 NDK 的东西仍然没有构建。有任何想法吗?似乎它正在构建其他所有东西,但只是跳过了 jni 的东西。
    • @NannuoLei 谢谢,我试过了,但我遇到了一个问题,即没有生成 .so。其他一切似乎都有效,但是当我在模拟器中运行 apkg 时,它抱怨它无法加载共享对象。
    • @aaa90210 你的模拟器是基于 x86 镜像的吗?默认情况下,NDK 只会生成一个 ARMEABI 库,如果你想构建一个 x86 图像,你可以在 Application.mk 中添加这一行: APP_ABI := armeabi x86
    • 它对我有用。 PS:看到这个答案的人,别忘了把Java_me_mattlogan_ndktest_MainActivity_stringFromJNI改成你自己的:)
    【解决方案8】:

    如果您使用的是 unix,最新版本 (0.8) 添加了 ndk-build。添加方法如下:

    android.ndk {
        moduleName "libraw"
    }
    

    它期望在'src/main/jni'下找到JNI,否则你可以定义它:

    sourceSets.main {
        jni.srcDirs = 'path'
    }
    

    截至 2014 年 1 月 28 日,版本 0.8 的构建在 Windows 上已损坏,您必须使用以下命令禁用构建:

    sourceSets.main {
        jni.srcDirs = [] //disable automatic ndk-build call (currently broken for windows)
    }
    

    【讨论】:

    • 该功能是否有任何文档?我找不到任何东西。目前这似乎完​​全忽略了我的 Android.mk/Application.mk。
    • 我没有找到。它可能已经半生不熟地潜入了构建中。我在 Windows 上,所以我只能确认它在尝试调用 unix ndk-build 脚本时失败。没有其他理由调用它然后将本机编译集成到 gradle 中。你在unix吗?
    • 它实际上希望在 jniLibs.srcDirs 中找到预构建的 *.so 文件
    • 我不同意,因为调用 ndk-build 会崩溃,如果它需要构建库,则绝对没有必要。我无法确认,因为我现在没有时间 vm Linux。
    【解决方案9】:

    https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/Z5yWAvCh4h4J 中显示了一个优雅的解决方法。

    基本上,您创建一个包含“lib/armeabi/yourlib.so”的 jar,然后在构建中包含该 jar。

    【讨论】:

    • 是的。仅当您不经常更改本机代码时,这才有效。您必须在存储库中包含二进制 jar 文件。否则你最终会得到一个构建脚本,它会动态创建一个 jar。
    • 我有 modified Android's Hello-JNI examplesimple bash script 包装 ndk-build,为每个 .so 生成 .jars 并将它们放在 gradle 的构建路径中以减轻这种痛苦。看看吧。
    【解决方案10】:

    another (closed) thread 中给出了自动打包易于编译的.so-文件的好答案。为了让它发挥作用,我不得不换行:

    from fileTree(dir: 'libs', include: '**/*.so')
    

    进入:

    from fileTree(dir: 'src/main/libs', include: '**/*.so') 
    

    如果没有此更改,将找不到 .so 文件,因此打包它们的任务将永远不会运行。

    【讨论】:

    • 更新:请注意,在较新的 Android Studios 中(至少在 1.5 中),原生代码的整合效果要好得多,因此无需单独执行此任务来打包代码。
    【解决方案11】:

    @plaisthos 的答案在最新的 gradle 版本中出现了问题,但仍有办法做到这一点。 在项目目录的根目录下创建一个native-libs 目录,并将我们所有的库复制到该目录中。

    将以下行添加到您的 build.gradle。建立并快乐。

    task copyNativeLibs(type: Copy) {
        from(new File(project(':<your project>').getProjectDir(), 'native-libs')) { include '**/*.so' }
        into new File(buildDir, 'native-libs')
    }
    
    tasks.withType(Compile) { compileTask -> compileTask.dependsOn copyNativeLibs }
    
    clean.dependsOn 'cleanCopyNativeLibs'
    

    【讨论】:

      【解决方案12】:

      这是我使用 gradle 中的 android-ndk 构建的代码。为此,在 gradle.properties 中添加 ndk 目录路径,即。添加ndkdir=/home/user/android-ndk-r9d 并将所有jni 文件放在src/main/ 中的文件夹native 中,如下面的代码所示。它将使用您可以正常使用的本机库创建 jar,如 System.loadLibrary("libraryname");

      dependencies {
          compile fileTree(dir: "$buildDir/native-libs", include: '*.jar')
      }
      
      task ndkBuild(type: Exec) {
          commandLine "$ndkdir/ndk-build", "--directory", "$projectDir/src/main/native", '-j', Runtime.runtime.availableProcessors(),
                  "APP_PLATFORM=android-8",
                  "APP_BUILD_SCRIPT=$projectDir/src/main/native/Android.mk",
                  "NDK_OUT=$buildDir/native/obj",
                  "NDK_APP_DST_DIR=$buildDir/native/libs/\$(TARGET_ARCH_ABI)"
      }
      
      task nativeLibsToJar(type: Jar, description: 'create a jar with native libs') {
          destinationDir file("$buildDir/native-libs")
          baseName 'native-libs'
          from fileTree(dir: "$buildDir/native/libs", include: '**/*.so')
          into 'lib/'
      }
      
      tasks.withType(JavaCompile) {
          compileTask -> compileTask.dependsOn nativeLibsToJar
      }
      
      nativeLibsToJar.dependsOn 'ndkBuild'
      

      【讨论】:

        【解决方案13】:

        我使用以下代码编译原生 Dropbox 库,我使用的是 Android Studio v1.1。

        task nativeLibsToJar(type: Zip) {
            destinationDir file("$buildDir/native-libs")
            baseName 'native-libs'
            extension 'jar'
            from fileTree(dir: 'src/main/libs', include: '**/*.so')
            into 'lib/'
        }
        
        tasks.withType(JavaCompile) {
            compileTask -> compileTask.dependsOn(nativeLibsToJar)
        }
        

        【讨论】:

          【解决方案14】:

          我在 android studio 项目的 local.properties 文件中使用了 ndk.dir=/usr/shareData/android-ndk-r11b // ndk

          的路径。和 在 android studio 项目的 gradle.properties 文件中添加这一行:
          android.useDeprecatedNdk=true



          更多信息在这里:http://tools.android.com/tech-docs/android-ndk-preview

          【讨论】:

            【解决方案15】:

            为了扩展 Naxos 所说的内容(感谢 Naxos 让我朝着正确的方向前进!),我从最近发布的 NDK 示例中学到了很多东西,并在此处发布了类似问题的答案。

            How to configure NDK with Android Gradle plugin 0.7

            这篇文章详细介绍了如何将预构建的原生库链接到您的应用中以适应各种架构,以及如何将 NDK 支持直接添加到 build.gradle 脚本中。在大多数情况下,您应该不再需要围绕 zip 和复制进行工作。

            【讨论】:

              【解决方案16】:

              以下是我用来让 NDK 在我的 Android Studio 项目中工作的步骤。 我用这个教程来帮助我 https://software.intel.com/en-us/videos/using-the-ndk-with-android-studio

              为了使用 NDK,您必须将 NDK 行添加到 local.properties。所以在你的 sdk.dir 下添加

              ndk.dir=C\:\\MyPathToMyNDK\ndk
              

              在我的应用 build.gradle 我有以下代码

                      ndk {
                          moduleName "myLib"
                          ldLibs "log"
                          stl "gnustl_shared"
                          cFlags "-std=c++11 -frtti -fexceptions -pthread"
                      }
              

              moduleName 是你想给你的本地代码起的名字。我相信这就是共享库的名称。 ldLibs 允许我登录到 LogCat,stl 是您要导入的 stl。有很多选项,与 Eclipse NDK 相同。 (http://www.kandroid.org/ndk/docs/CPLUSPLUS-SUPPORT.html)

              cFlags 对我来说仍然是某种黑魔法。我还没有找到所有选项以及它们给我的东西的好来源。在 StackOverflow 周围搜索你需要的任何东西,这就是我找到它的地方。我知道 c++11 允许我使用新的 c++11 标准。

              这是我如何从本机代码登录到 LogCat 的示例

              __android_log_print(ANDROID_LOG_DEBUG, "TestApp", "Adding - String %d has a field name of %s and a value of %s", i, lKeyUTF8.c_str(), lValueUTF8.c_str());
              

              【讨论】:

                【解决方案17】:

                在 eclipse 中的 android studio 中配置项目:你必须将 eclipse ndk 项目导入到 android studio 而不导出到 gradle 并且它可以工作,你还需要在 local 中添加 ndk 的路径。属性,如果显示错误则添加

                sourceSets.main {
                        jniLibs.srcDir 'src/main/libs' 
                        jni.srcDirs = [] //disable automatic ndk-build callenter code here
                    }
                

                build.gradle 文件中然后使用终端创建 jni 文件夹和文件并运行它会工作

                【讨论】:

                • 见我自己的答案。这是我目前正在使用的解决方法,但它并不是真正的解决方案。
                【解决方案18】:

                现在 Android Studio 处于稳定版本,运行 android-ndk samples 非常简单。这些示例使用ndk experimental plugin,并且比从 Android NDK 在线文档链接到的示例更新。一旦你知道它们可以工作,你就可以研究 build.gradle、local.properties 和 gradle-wrapper.properties 文件并相应地修改你的项目。以下是让它们工作的步骤。

                1. 转到设置、外观和行为、系统设置、Android SDK,选择 SDK 工具选项卡,然后检查列表底部的 Android NDK 版本 1.0.0。这将下载 NDK。

                2. 指向新下载的 NDK 的位置。请注意,它将被放置在 sdk/ndk-bundle 目录中。通过选择文件、项目结构、SDK 位置(左侧)并在 Android NDK 位置下提供路径来执行此操作。这将向 local.properties 添加一个 ndk 条目,类似于:

                  Mac/Linux:ndk.dir=/Android/sdk/ndk-bundle
                  Windows:ndk.dir=C:\Android\sdk\ndk-bundle

                我已经以这种方式成功构建和部署了存储库中的所有项目,除了gles3gni、native-codec和builder。我正在使用以下内容:

                Android Studio 1.3 构建 AI-141.2117773
                2015 年 7 月 28 日发布的 android-ndk 示例(以上链接)
                SDK 工具 24.3.3
                NDK r10e 解压到 C:\Android\sdk\ndk-bundle
                摇篮 2.5
                Gradle 插件 0.2.0
                Windows 8.1 64 位

                【讨论】:

                  【解决方案19】:

                  NDK 构建和 gradle(基本)

                  通常使用 NDK 构建就像正确指定 Android.mk 的 ndkBuild 路径或 CMakeLists.txt 的 cmake 路径一样简单。我推荐 CMake 而不是较旧的 Android.mk,因为 Android Studio 的 C/C++ 支持基于 CLion,并且它使用 CMake 作为其项目格式。根据我的经验,这往往会使 IDE 对大型项目的响应速度更快。您项目中编译的所有内容都将自动构建并复制到 APK 中。

                  apply plugin: 'com.android.library'
                  
                  android {
                      compileSdkVersion 19
                      buildToolsVersion "25.0.2"
                  
                      defaultConfig {
                          minSdkVersion 19
                          targetSdkVersion 19
                  
                          ndk {
                              abiFilters 'armeabi', 'armeabi-v7a', 'x86'
                              // 64-bit support requires an Android API level higher than 19; Namely 21 and higher
                              //abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
                          }
                  
                          externalNativeBuild {
                              cmake {
                                  arguments '-DANDROID_TOOLCHAIN=clang',
                                          '-DANDROID_PLATFORM=android-19',
                                          '-DANDROID_STL=gnustl_static',
                                          '-DANDROID_ARM_NEON=TRUE'
                  
                              }
                          }
                      }
                  
                      externalNativeBuild {
                          cmake {
                              path 'src/main/jni/CMakeLists.txt'
                          }
                      }
                  }
                  
                  dependencies {
                      compile fileTree(dir: 'libs', include: ['*.jar'])
                  }
                  

                  将预建库添加到项目中(高级)

                  您的 NDK 构建中的静态库 (.a) 将自动包含在内,但预构建的动态库 (.so) 需要放置在 jniLibs 中。这可以使用sourceSets 进行配置,但您应该采用标准。包含预构建库时,您不需要在 build.gradle 中添加任何其他命令。

                  jniLibs的布局

                  您可以在Android Gradle Plugin User Guide 中找到有关该结构的更多信息。

                  |--app:
                  |--|--build.gradle
                  |--|--src:
                  |--|--|--main
                  |--|--|--|--java
                  |--|--|--|--jni
                  |--|--|--|--|--CMakeLists.txt
                  |--|--|--|--jniLibs
                  |--|--|--|--|--armeabi
                  |--|--|--|--|--|--.so Files
                  |--|--|--|--|--armeabi-v7a
                  |--|--|--|--|--|--.so Files
                  |--|--|--|--|--x86
                  |--|--|--|--|--|--.so Files
                  

                  然后您可以验证生成的 APK 是否包含您的 .so 文件,通常在 build/outputs/apk/ 下,使用 unzip -l myApp.apk 列出内容。

                  构建共享库

                  如果您在 NDK 中构建共享库,则无需进一步执行任何操作。它将正确捆绑在 APK 中。

                  【讨论】:

                    【解决方案20】:

                    只需将此行添加到应用程序build.gradle

                    dependencies {
                        ...
                        compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')
                    }
                    
                    task nativeLibsToJar(type: Zip, description: 'create a jar archive of the native libs') {
                        destinationDir file("$buildDir/native-libs")
                        baseName 'native-libs'
                        extension 'jar'
                        from fileTree(dir: 'libs', include: '**/*.so')
                        into 'lib/armeabi/'
                    }
                    
                    tasks.withType(JavaCompile) {
                        compileTask -> compileTask.dependsOn(nativeLibsToJar)
                    }
                    

                    【讨论】:

                    • 我认为 jniLibs.srcDirs 方法比这更干净,因为您可以使用 abiFilter/flavors 但您的方法也应该有效。
                    【解决方案21】:

                    现在。我可以加载这么成功了!

                    1.将.so文件添加到该路径

                    Project:
                    

                    |--src |--|--主要 |--|--|--java |--|--|--jniLibs |--|--|--|--armeabi |--|--|--|--|--.so 文件

                    2.将此代码添加到gradle.build

                    android {
                    splits {
                        abi {
                            enable true
                            reset()
                            include 'x86', 'x86_64', 'arm64-v8a', 'armeabi-v7a', 'armeabi'
                            universalApk false
                        }
                    }
                    

                    }

                    3.System.loadLibrary("yousoname");

                    1. 祝你好运,gradle 1.2.3 没问题

                    【讨论】:

                      【解决方案22】:
                      1. 如果你的项目是从eclipse导出的,在gradle文件中添加如下代码:

                        android {
                           sourceSets{
                                main{
                                   jniLibs.srcDir['libs']  
                              }  
                            }
                        }
                        

                      2.如果你在Android studio中创建项目:

                      在 src/main/ 中创建一个名为 jniLibs 的文件夹,并将你的 *.so 文件放入 jniLibs 文件夹中。

                      并在你的gradle文件中复制如下代码:

                      android {
                          sourceSets{  
                             main{  
                               jniLibs.srcDir['jniLibs']  
                            }  
                          }
                      }
                      

                      【讨论】:

                        【解决方案23】:

                        虽然我相信 SJoshi (oracle guy) 有最完整的答案,但 SWIG 项目是一个特例,有趣且有用,但对于大多数使用标准 SDK ant 做得很好的项目来说,并没有通用基于项目 + NDK。我们都希望现在最有可能使用 Android Studio,或者希望为移动设备提供更 CI 友好的构建工具链,这在理论上 gradle 提供。

                        我已经发布了我的方法,从某个地方借来的(我在 SO 上找到了这个,但发布了 app build.gradle 的要点:https://gist.github.com/truedat101/c45ff2b69e91d5c8e9c7962d4b96e841)。简而言之,我建议如下:

                        • 不要将您的项目升级到最新的 gradle 版本
                        • 在您的项目根目录中使用 com.android.tools.build:gradle:1.5.0
                        • 在您的应用项目中使用 com.android.application
                        • 确保 gradle.properties 具有:android.useDeprecatedNdk=true(以防它抱怨)
                        • 使用上述方法可确保您在创建 Android.mk 文件时所付出的努力不会白费。您可以控制要构建的目标拱门。这些说明对 Windows 用户很友好,理论上他们应该能够在没有特殊问题的情况下在 Windows 上进行构建。

                        在我看来,Gradle for Android 一团糟,就像我喜欢借用的 maven 概念和自以为是的项目目录结构一样。此 NDK 功能已“即将推出”近 3 年多。

                        【讨论】:

                          猜你喜欢
                          • 2014-01-22
                          • 1970-01-01
                          • 2015-07-29
                          • 2016-01-19
                          • 1970-01-01
                          • 2014-06-14
                          • 2017-09-19
                          • 2016-08-07
                          • 1970-01-01
                          相关资源
                          最近更新 更多