Android Studio 中的 JNI 和 Gradle [英] JNI and Gradle in Android Studio

查看:39
本文介绍了Android Studio 中的 JNI 和 Gradle的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将本机代码添加到我的应用中.我在 ../main/jni 中拥有所有东西,就像在我的 Eclipse 项目中一样.我已将 ndk.dir=... 添加到我的 local.properties.我还没有做任何其他事情(我不确定实际上还需要什么,所以如果我错过了什么,请告诉我).当我尝试构建时出现此错误:

I'm trying to add native code to my app. I have everything in ../main/jni as it was in my Eclipse project. I have added ndk.dir=... to my local.properties. I haven't done anything else yet (I'm not sure what else is actually required, so if I've missed something let me know). When I try and build I get this error:

Execution failed for task ':app:compileDebugNdk'.
> com.android.ide.common.internal.LoggedErrorException: Failed to run command:
    /Users/me/android-ndk-r8e/ndk-build NDK_PROJECT_PATH=null 
APP_BUILD_SCRIPT=/Users/me/Project/app/build/ndk/debug/Android.mk APP_PLATFORM=android-19 
NDK_OUT=/Users/me/Project/app/build/ndk/debug/obj 
NDK_LIBS_OUT=/Users/me/Project/app/build/ndk/debug/lib APP_ABI=all

  Error Code:
    2
  Output:
    make: *** No rule to make target `/Users/me/Project/webapp/build/ndk/debug//Users/me/Project/app/src/main/jni/jni_part.cpp',
 needed by `/Users/me/Project/app/build/ndk/debug/obj/local/armeabi-v7a/objs/webapp//Users/me/Project/app/src/main/jni/jni_part.o'.  
Stop.

我需要做什么?

Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

# OpenCV
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
include .../OpenCV-2.4.5-android-sdk/sdk/native/jni/OpenCV.mk

LOCAL_MODULE    := native_part
LOCAL_SRC_FILES := jni_part.cpp
LOCAL_LDLIBS +=  -llog -ldl

include $(BUILD_SHARED_LIBRARY)

Application.mk:

APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi armeabi-v7a
APP_PLATFORM := android-8

推荐答案

Gradle Build Tools 2.2.0+ - NDK 最接近被称为魔法"的版本

为了避免实验性的并坦率地厌倦了 NDK 及其所有黑客行为,我很高兴 Gradle 构建工具的 2.2.x 版出来了,现在它可以正常工作了.关键是 externalNativeBuild 并将 ndkBuild 路径参数指向 Android.mk 或将 ndkBuild 更改为 cmake 并将路径参数指向 CMakeLists.txt 构建脚本.

Gradle Build Tools 2.2.0+ - The closest the NDK has ever come to being called 'magic'

In trying to avoid experimental and frankly fed up with the NDK and all its hackery I am happy that 2.2.x of the Gradle Build Tools came out and now it just works. The key is the externalNativeBuild and pointing ndkBuild path argument at an Android.mk or change ndkBuild to cmake and point the path argument at a CMakeLists.txt build script.

android {
    compileSdkVersion 19
    buildToolsVersion "25.0.2"

    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 19

        ndk {
            abiFilters 'armeabi', 'armeabi-v7a', 'x86'
        }

        externalNativeBuild {
            cmake {
                cppFlags '-std=c++11'
                arguments '-DANDROID_TOOLCHAIN=clang',
                        '-DANDROID_PLATFORM=android-19',
                        '-DANDROID_STL=gnustl_static',
                        '-DANDROID_ARM_NEON=TRUE',
                        '-DANDROID_CPP_FEATURES=exceptions rtti'
            }
        }
    }

    externalNativeBuild {
        cmake {
             path 'src/main/jni/CMakeLists.txt'
        }
        //ndkBuild {
        //   path 'src/main/jni/Android.mk'
        //}
    }
}

有关更多详细信息,请查看 Google 关于添加本机代码的页面.

For much more detail check Google's page on adding native code.

正确设置后,您可以 ./gradlew installDebug 并开始使用.您还需要注意 NDK 正在转向 clang,因为 gcc 现在在 Android NDK 中已被弃用.

After this is setup correctly you can ./gradlew installDebug and off you go. You will also need to be aware that the NDK is moving to clang since gcc is now deprecated in the Android NDK.

其他答案确实指出了防止自动创建 Android.mk 文件的正确方法,但他们没有采取与 Android Studio 更好地集成的额外步骤.我添加了从源代码实际清理和构建的功能,而无需转到命令行.你的 local.properties 文件需要有 ndk.dir=/path/to/ndk

The other answers do point out the correct way to prevent the automatic creation of Android.mk files, but they fail to go the extra step of integrating better with Android Studio. I have added the ability to actually clean and build from source without needing to go to the command-line. Your local.properties file will need to have ndk.dir=/path/to/ndk

apply plugin: 'com.android.application'

android {
    compileSdkVersion 14
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.example.application"
        minSdkVersion 14
        targetSdkVersion 14

        ndk {
            moduleName "YourModuleName"
        }
    }

    sourceSets.main {
        jni.srcDirs = [] // This prevents the auto generation of Android.mk
        jniLibs.srcDir 'src/main/libs' // This is not necessary unless you have precompiled libraries in your project.
    }

    task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
        def ndkDir = android.ndkDirectory
        commandLine "$ndkDir/ndk-build",
                '-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
                '-j', Runtime.runtime.availableProcessors(),
                'all',
                'NDK_DEBUG=1'
    }

    task cleanNative(type: Exec, description: 'Clean JNI object files') {
        def ndkDir = android.ndkDirectory
        commandLine "$ndkDir/ndk-build",
                '-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
                'clean'
    }

    clean.dependsOn 'cleanNative'

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

dependencies {
    compile 'com.android.support:support-v4:20.0.0'
}

src/main/jni 目录采用项目的标准布局.它应该是从这个 build.gradle 文件位置到 jni 目录的相对位置.

The src/main/jni directory assumes a standard layout of the project. It should be the relative from this build.gradle file location to the jni directory.

另请查看此堆栈溢出答案.

您的 gradle 版本和常规设置是否正确非常重要.如果您有一个较旧的项目,我强烈建议您使用最新的 Android Studio 创建一个新项目,并查看 Google 认为的标准项目.另外,使用 gradlew.这可以保护开发人员免受 gradle 版本不匹配的影响.最后,必须正确配置gradle插件.

It is really important that your gradle version and general setup are correct. If you have an older project I highly recommend creating a new one with the latest Android Studio and see what Google considers the standard project. Also, use gradlew. This protects the developer from a gradle version mismatch. Finally, the gradle plugin must be configured correctly.

还有你问gradle插件最新版本是什么?检查工具页面并相应地编辑版本.

And you ask what is the latest version of the gradle plugin? Check the tools page and edit the version accordingly.

// Top-level build file where you can add configuration options common to all sub-projects/modules.

// Running 'gradle wrapper' will generate gradlew - Getting gradle wrapper working and using it will save you a lot of pain.
task wrapper(type: Wrapper) {
    gradleVersion = '2.2'
}

// Look Google doesn't use Maven Central, they use jcenter now.
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.2.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

确保 gradle wrapper 生成 gradlew 文件和 gradle/wrapper 子目录.这是一个大问题.

Make sure gradle wrapper generates the gradlew file and gradle/wrapper subdirectory. This is a big gotcha.

这已经出现了很多次,但是android.ndkDirectory是1.1之后获取文件夹的正确方法.将 Gradle 项目迁移到 1.0.0 版.如果您使用的是该插件的实验版或旧版,您的使用情况可能会有所不同.

This has come up a number of times, but android.ndkDirectory is the correct way to get the folder after 1.1. Migrating Gradle Projects to version 1.0.0. If you're using an experimental or ancient version of the plugin your mileage may vary.

这篇关于Android Studio 中的 JNI 和 Gradle的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆