안드로이드 스튜디오, gradle 및 NDK


153

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

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

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



24
새로운 독자 :이 질문은 Android Studio 베타 기간 동안 처음에 요청되었습니다. 대답은 시간이 지남에 따라 변경되었습니다. 답변에 언급 된 Gradle 버전과 답변이 실제로 게시 된시기에주의하십시오.
Sean Beach

무언가가 정말로 바뀌면 나는 상태를 반영하기 위해 질문을 편집 할 것입니다
plaisthos

카나리아 채널의 Android Studio 1.3은 NDK를 완벽하게 지원합니다. 참조 : tools.android.com/download/studio/canary/latest
Vikasdeep Singh

2015 년 6 월 18 일 : 베타 채널에서 Android Studio 1.3 베타를 사용할 수 있습니다! 죄송합니다.이 빌드에는 아직 C / C ++ 지원이 포함되어 있지 않습니다. 출처 : tools.android.com/recent/androidstudio13beta 사용 가능
fastr.de

답변:


85

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


2
나는 안드로이드 스튜디오 (및 Gradle을 지원)에서 디버깅 NDK 및 명령 완료를 사용할 수 있다면 좋은 것
powder366

1
@GREnvoy-Android 스튜디오에서 올바른 NDK 빌더를 어떻게 구성합니까? 당신은 PLZ 나에게 단계를 줄 수 있습니까? :)
Shravan

7
@DirtyBeach 왜 구식입니까? 여전히 Studio에서 NDK의 통합이 없습니다. 현재 노력하고 있지만 현재 ETA는 없습니다.
Xavier Ducrohet

2
나의 행동은 내가 "통합"을 어떻게 정의하고 있 었는가에 근거했다. 나는 그것이 존재하지는 않지만 "그레이들과 함께 NDK를 사용하는 방법"을 의미한다는 것을 이해했다. 그러나 귀하의 의견에 따르면 귀하의 팀은 진정한 통합이 될 수있는 다른 것을 염두에두고있는 것 같습니다. 이전 진술을 철회합니다.
Sean Beach

2
NDK 통합은 Google IO 2015에서 발표되었습니다. Android Studio 1.3에서 사용할 수 있습니다 (미리보기를 곧 다운로드 할 수 있습니다. 가능한 경우 링크를 게시하겠습니다).
Cypress Frankenfeld

43

업데이트 : 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파일 이없는 경우 빌드는 불행히도 실패하지 않습니다 .


5
새로운 Android Studio 버전에서는 더 이상 작동하지 않습니다.
powder366

@ powder366 내 대답을 참조하십시오.
Leandros

2
약간의 Groovy 마술 : tasks.withType(com.android.build.gradle.tasks.PackageApplication) { it.jniFolders = [file("libs")] as Set }. 도와 주셔서 감사합니다!
trnl

안드로이드 스튜디오 0.8.9 절차 란
Pandiri 디팍

1
@plaisthos 올바른 방향을 지적 해 주셔서 감사합니다! gradle 스크립트의 두 번째 줄은 jni.srcDirs = [] //disable automatic ndk-buildAndroid Studio가 C / C ++ 소스 코드를 다시 작성하지 못하게하기 때문에 매우 중요합니다. 나는 당신의 게시물을 볼 때까지 이틀 동안 이것을 알아 내려고 노력했으며 이것이 내 문제를 해결했습니다. 실제로 NDK 빌드는 40 년 이상 Makefile에 의해 C / C ++가 빌드 되었기 때문에 gradle 스크립트가 아닌 Android.mk 명령 줄 makefile만으로 별도로 빌드하는 것이 좋습니다.
tonga

40

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 생성 래퍼에 대한 자동 완성 기능이 있습니다.

C ++-Java 랩퍼의 자동 완성 예

그러나 완전히 장미 빛이 아닙니다 ... SWIG를 사용하여 라이브러리를 자동 생성하여 코드를 자동 생성 한 다음 기본 키워드 자동 생성을 사용하려고하면 Swig _wrap의 잘못된 위치에 코드가 배치됩니다 .cxx 파일 ... 따라서 "extern C"블록으로 이동해야합니다.

C ++-Java 랩퍼가 올바른 위치로 이동했습니다.

업데이트 : 2017 년 10 월 15 일

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

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

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


1
* .so를 (module) / src / main / jniLibs에 넣으십시오.
fawkes

디버그 빌드에서도 Android Studio를 사용할 때
NDEBUG

35

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
}

예. 그러나 이것은 Unix 플랫폼에서만 작동하며 매우 간단한 ndk 구성 / 메이크 파일보다 복잡한 경우에도 제한됩니다.
plaisthos

예, gradle 빌드 파일에서 설정할 수있는 제한된 것들에 대해 makefile을 자동 생성하지만 해결 방법이 있습니다. 나는 그것을 내 대답에 추가했다.
Cypress Frankenfeld

1
ndk-build에 대한 호출은 Android Studio가 아닌 명령 줄에서만 작동합니다.
카메론 로웰 팔머

이것이 가장 최근의 대답은 아니지만 가장 정확한 것으로 보입니다. 3 단계 : " 최신 gradle 샘플 프로젝트 다운로드"에 특히주의하십시오 .
Sean Beach

4
src dir을 비활성화하는 대신이 핵을 사용하므로 IDE 내에서 c / c ++ 파일을 편집 할 수 있습니다.tasks.all { task -> if (task.name.contains('Ndk')) task.enabled = false }
sherpya

23

"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


16

현재 (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 제외).


현재 프로젝트에서 지시 한대로 정확하게 작업하고 있지만 NDK는 아직 빌드되지 않았습니다. 어떤 아이디어? 그것은 다른 모든 것을 만들고 있지만 jni 물건을 건너 뛰는 것처럼 보입니다.
alice.harrison

@NannuoLei 감사합니다, 시도했지만 .so가 생성되지 않는 문제가 발생합니다. 다른 모든 것이 작동하는 것처럼 보이지만 에뮬레이터에서 apkg를 실행하면 공유 객체를로드 할 수 없다고 불평합니다.
aaa90210

@ aaa90210은 에뮬레이터가 x86 이미지를 기반으로합니까? 기본적으로 NDK는 ARMEABI 라이브러리를 생성합니다. x86 이미지를 빌드하려는 경우이 줄을 Application.mk에 추가 할 수 있습니다. APP_ABI : = armeabi x86
Leo는 Monica Cellio를 지원합니다.

1
그것은 나와 함께 일했다. 추신 :이 답변을 보는 사람 Java_me_mattlogan_ndktest_MainActivity_stringFromJNI은 자신의 것으로 변경 하는 것을 잊지 마십시오 :)
AbdulMomen عبدالمؤمن

8

유닉스에 있다면 최신 버전 (0.8)이 ndk-build를 추가합니다. 추가하는 방법은 다음과 같습니다.

android.ndk {
    moduleName "libraw"
}

'src / main / jni'에서 JNI를 찾을 것으로 예상되며, 그렇지 않으면 다음과 같이 정의 할 수 있습니다.

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

버전 0.8의 2014 년 1 월 28 일 현재 빌드가 Windows에서 손상되었으므로 다음을 사용하여 빌드를 비활성화해야합니다.

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

1
해당 기능에 대한 설명서가 있습니까? 나는 찾을 수 없었다. 현재 내 Android.mk/Application.mk를 완전히 무시하는 것 같습니다.
plaisthos

나는 아무것도 찾지 못했다. 반쯤 구운 빌드에 들어갈 수 있습니다. 나는 Windows에있어서 유닉스 ndk-build 스크립트를 호출하려고 시도 할 때만 실패한다는 것을 확인할 수 있습니다. 그런 다음 네이티브 컴파일을 gradle에 통합하기 위해 호출 할 다른 이유가 없습니다. 유닉스에 있습니까?
Anthony


실제로 jniLibs.srcDirs에 * .so를 파일을 사전 구축을 찾을 것으로 예상
알파인

빌드 라이브러리가 필요한 경우 절대적으로 필요하지 않은 ndk-build 호출이 충돌한다는 사실에 동의하지 않습니다. 지금 vm Linux를 사용할 시간이 없기 때문에 확인할 수 없습니다.
Anthony

7

우아한 해결 방법은 https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/Z5yWAvCh4h4J에 나와 있습니다 .

기본적으로 "lib / armeabi / yourlib.so"를 포함하는 jar을 생성 한 다음 jar을 빌드에 포함시킵니다.


네. 코드를 자주 변경하지 않으면 잘 작동합니다. 그리고 저장소에 바이너리 jar 파일을 포함시켜야합니다. 그렇지 않으면 즉시 항아리를 만드는 빌드 스크립트가 생깁니다.
plaisthos

1
나는 한 안드로이드의 안녕 - JNI 예제를 수정간단한 bash는 스크립트 랩가 ndk-build발생, .jar각각의 .so이 고통을 완화하기 위해 Gradle을의 빌드 경로와 장소를. 확인 해봐.
dbro

4

쉽게 컴파일 된 파일의 패키징을 자동화하는 좋은 대답 .so다른 (닫힌) 스레드에 있습니다. 그 작업을 수행하려면 줄을 바꿔야했습니다.

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

으로:

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

이 변경이 없으면 .so파일을 찾을 수 없으므로 파일을 포장하는 작업이 실행되지 않습니다.


업데이트 : 최신 Android Studio (최소 1.5 이상)에서는 기본 코드가 훨씬 잘 통합되어 있으므로 코드를 패키징하기 위해 별도의 작업을 수행 할 필요가 없습니다.
HYS

4

@plaisthos의 답변은 최신 gradle 버전에서 중단되었지만 여전히 수행 할 수있는 방법이 있습니다. 만들기 native-libs프로젝트 디렉토리의 루트 디렉토리를이 디렉토리에 모든 y를 우리의 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'

3

이것은 gradle에서 android-ndk를 사용하여 빌드하는 데 사용하는 코드입니다. 이를 위해 gradle.propertiesie 에 ndk 디렉토리 경로를 추가하십시오 . 아래에 게시 된 코드에서 볼 수 있듯이 ndkdir=/home/user/android-ndk-r9d모든 jni 파일을 폴더 native에 추가 하고 넣습니다 src/main/. 다음과 같이 정상적으로 사용할 수있는 기본 라이브러리가있는 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'

3

기본 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)
}


1

Naxos가 말한 것을 확장하기 위해 (Naxos가 올바른 방향으로 보내 주셔서 감사합니다!) 최근에 발표 된 NDK 예제에서 많은 것을 배웠고 비슷한 질문에 대한 답변을 여기에 게시했습니다.

Android Gradle 플러그인 0.7을 사용하여 NDK를 구성하는 방법

이 게시물에는 다양한 아키텍처의 사전 빌드 된 기본 라이브러리를 앱에 링크하는 방법과 build.gradle 스크립트에 NDK 지원을 직접 추가하는 방법에 대한 자세한 정보가 있습니다. 대부분의 경우 zip을 해결하고 더 이상 복사하지 않아도됩니다.


1

NDK를 Android Studio 프로젝트에서 작동시키는 데 사용한 단계는 다음과 같습니다. 이 자습서를 사용하여 https://software.intel.com/en-us/videos/using-the-ndk-with-android-studio

NDK를 사용하려면 local.properties에 NDK 행을 추가해야합니다. 따라서 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());

1

Eclipse 에서 android studio 로 프로젝트 구성 : gradle로 내 보내지 않고 Eclipse ndk 프로젝트를 android studio로 가져와야하며 작동합니다. 또한 local.properties 에 ndk의 경로를 추가해야합니다. 오류가 표시되면 추가하십시오.

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

build.gradle 파일 에서 터미널을 사용하여 jni 폴더와 파일을 만들고 실행하면 작동합니다.


1
내 대답을 참조하십시오. 이것이 현재 사용중인 해결 방법이지만 실제로 해결책은 아닙니다.
plaisthos

1

이제 Android Studio가 안정적인 채널에 있으므로 android-ndk 샘플을 실행 하는 것이 매우 간단합니다 . 이 샘플은 ndk 실험 플러그인을 사용하며 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 위치 아래에 경로를 제공하면됩니다. 이것은 다음과 비슷한 ndk 항목을 local.properties에 추가합니다.

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

gles3gni, native-codec 및 builder를 제외한 모든 방식으로 저장소에 모든 프로젝트를 빌드하고 배치했습니다. 나는 다음을 사용하고 있습니다 :

Android Studio 1.3 빌드 AI-141.2117773
2015 년 7 월 28 일에 게시 된 android-ndk 샘플 (위 링크)
SDK 도구 24.3.3
C : \ Android \ sdk \ ndk-bundle
Gradle 2.5
Gradle 플러그인 0.2.0
Windows 8.1 64 비트로 추출 된 NDK r10e


1

NDK 빌드 및 gradle (기본)

일반적으로 NDK로 빌드하는 것은 Android.mk에 대한 ndkBuild 경로 또는 CMakeLists.txt에 대한 cmake 경로를 올바르게 지정하는 것만 큼 간단합니다. Android Studio의 C / C ++ 지원은 CLion을 기반으로하며 CMake를 프로젝트 형식으로 사용하므로 이전 Android.mk보다 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 사용 설명서 에서 찾을 수 있습니다 .

|--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에 올바르게 번들로 제공됩니다.


0

이 줄을 앱에 추가하십시오. 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 / flavours를 사용할 수 있기 때문에 이것보다 깨끗하다고 ​​생각하지만 접근 방식도 작동해야합니다.
plaisthos

0

이제 성공할 수 있습니다!

1.이 경로에 .so 파일을 추가하십시오.

Project:

| --src |-| --main |-|-| --java |-|-| --jniLibs |-|-|-| --armeabi |-|- |-|-|-. so 파일

2.이 코드를 gradle.build에 추가하십시오

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

}

삼.System.loadLibrary("yousoname");

  1. 당신을 위해 행운을 빕니다, 그것은 gradle 1.2.3에 좋습니다

0
  1. 프로젝트를 이클립스에서 내 보낸 경우 아래 코드를 gradle 파일에 추가하십시오.

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

2. Android 스튜디오에서 프로젝트를 생성하는 경우 :

src / main /에 jniLibs라는 폴더를 만들고 * .so 파일을 jniLibs 폴더에 넣습니다.

그리고 gradle 파일에 아래와 같이 코드를 복사하십시오.

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

0

SJoshi (오라클 가이)가 가장 완전한 답을 가지고 있다고 생각하지만, SWIG 프로젝트는 흥미롭고 유용한 특별한 사례이지만 표준 SDK 개미 기반 프로젝트로 잘 수행 한 대부분의 프로젝트에는 일반화되지 않았습니다. NDK. 우리 모두는 지금 안드로이드 스튜디오를 가장 많이 사용하고 있거나 이론적으로 제공하는 모바일 용 CI 친화적 인 빌드 툴체인을 원합니다.

어딘가에서 빌린 내 접근 방식을 게시했습니다 (SO에서 이것을 찾았지만 앱 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 사용자에게 친절합니다.

내가 빌린 maven 개념과 프로젝트 디렉토리의 구조를 좋아하는 것처럼 Android 용 Gradle은 내 의견에 혼란스러워했다. 이 NDK 기능은 거의 3 년 이상 "곧 제공 될 예정"입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.