안드로이드 스튜디오, gradle 및 NDK 사용하여 안드로이드

이 전체 gradle 및 Android Studio 지원에 매우 익숙합니다. 내보내기 옵션을 사용하여 안드로이드 프로젝트를 gradle로 변환했습니다.

그러나 NDK 빌드를 gradle 빌드 프로세스에 통합하는 방법에 대한 문서 또는 시작 지점을 찾고 있습니다.

가능한 경우 빌드 바이너리 (.so 파일)를 자산 디렉토리에 복사하는 일종의 “후”단계도 필요합니다.



답변

1.3의 미리보기로 통합의 첫 번째 버전을 출시했습니다. http://tools.android.com/tech-docs/android-ndk-preview

통합은 1.3이 최종이 된 후에도 미리보기를 유지합니다. 최종 시점 (2015/07/10 기준)에 대한 현재 ETA가 없습니다.

자세한 정보는 여기 : http://tools.android.com/tech-docs/android-ndk-preview


답변

업데이트 : 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를 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 애플리케이션에로드하려는 외부 라이브러리가있는 경우 기본적으로 (모듈) / src / main / jniLibs에서 찾습니다. 모듈의 build.gradle에서 sourceSets.main.jniLibs.srcDirs를 설정하여이를 변경할 수 있습니다. 대상으로하는 각 아키텍처 (예 : x86, arm, mips, arm64-v8a 등)에 대한 라이브러리가있는 하위 디렉토리가 필요합니다.

NDK 툴체인에서 기본적으로 컴파일하려는 코드는 (module) / src / main / jni에 있으며 위와 비슷하게 모듈의 build.gradle에서 sourceSets.main.jni.srcDirs를 설정하여 변경할 수 있습니다.

이것을 모듈의 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 섹션을 사용해야한다고 생각합니다. 또한 CLion이 자동으로 수행하지 않는 한 Java <-> C ++ 래퍼 파일을 작성해야 할 필요가 있다고 생각합니다.

업데이트 : 2016 년 1 월 5 일

최신 실험 Gradle 플러그인 (0.6.0-alpha3)과 함께 Android Studio 1.5를 사용하도록 블로그와 Github 저장소 (개발 지점)를 업데이트했습니다.

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를 사용하여 라이브러리를 자동 생성하여 코드를 자동 생성 한 다음 기본 키워드 자동 생성을 사용하려고하면 Swig _wrap의 잘못된 위치에 코드가 배치됩니다 .cxx 파일 … 따라서 “extern C”블록으로 이동해야합니다.

업데이트 : 2017 년 10 월 15 일

Android Studio 2.2 이상에서 Gradle 및 CMake를 통해 NDK 툴 체인에 대해 기본적으로 ‘원시'(펀칭 없음) 지원을 제공한다는 점을 언급하지 않은 경우에는 기각됩니다. 이제 새 프로젝트를 만들 때 C ++ 지원을 선택하기 만하면됩니다.

여전히 자신의 JNI 계층 코드를 생성하거나 위에서 언급 한 SWIG 기술을 사용해야하지만 Android 프로젝트에서 C ++의 스캐 폴딩은 이제 간단합니다.

CMakeLists 파일 (C ++ 소스 파일을 저장하는 위치)의 변경 사항은 Android Studio에서 선택되며 관련 라이브러리는 자동으로 다시 컴파일됩니다.


답변

Google IO 2015에서 Google은 Android Studio 1.3에서 전체 NDK 통합을 발표했습니다.

이제 미리 볼 수 없으며 모든 사람이 사용할 수 있습니다 : https://developer.android.com/studio/projects/add-native-code.html

기존 답변 : 프로젝트 소스에 디렉토리 ndk-build가 있으면 Gradle이 자동으로 호출 jni합니다.

이것은 안드로이드 스튜디오 0.5.9 (카나리아 빌드)에서 작동합니다.

  1. NDK 다운로드

  2. 하나 추가 ANDROID_NDK_HOME환경 변수 또는 추가 ndk.dir=/path/to/ndk당신에게 local.properties당신의 안드로이드 Studio 프로젝트에. 이를 통해 Android Studio는 ndk를 자동으로 실행할 수 있습니다.

  3. 최신 gradle 샘플 프로젝트 를 다운로드하여 ndk 프로젝트 의 예를보십시오. 페이지 하단에 있습니다. 좋은 샘플 프로젝트는 ndkJniLib입니다.

  4. gradle.buildNDK 샘플 프로젝트에서를 복사하십시오 . 이런 식으로 보일 것입니다. 이것은 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에 atuomatic 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
}

답변

“gradle 1.11 com.android.tools.build:gradle:0.9.+”는 사전 빌드 ndk를 지원합니다. * .so를 src / main / jniLibs 디렉토리에 넣을 수 있습니다. gradle을 빌드하면 ndk가 올바른 위치에 패키지됩니다.

여기 내 프로젝트가 있습니다

계획:
| --src
|-|-주요
|-|-| --java
|-|-| --jniLibs
|-|-|-| --armeabi
|-|-|-|-|-. so 파일
| --libs
|-| --other.jar

답변

Xavier가 말했듯이 gradle 0.7.2 이상을 사용하는 경우 사전 빌드를 / src / main / jniLibs /에 넣을 수 있습니다

https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/ctDp9viWaxoJ 에서 가져옴


답변

현재 (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'])
}

여기에서 매우 유사한 앱의 전체 소스 코드를 찾으십시오 (NDK 제외).