Android Studio, Gradle i NDK


153

Jestem bardzo nowy w tej całej obsłudze Gradle i Android Studio. Udało mi się przekonwertować mój projekt na Androida do gradle przy użyciu opcji eksportu.

Ale szukam dokumentacji lub punktu wyjścia, jak zintegrować kompilację NDK z procesem budowania gradle.

Jeśli to możliwe, potrzebuję również jakiegoś etapu „po”, który kopiuje pliki binarne kompilacji (pliki .so) do katalogu zasobów.


Opublikowałem swoją odpowiedź w poniższym linku stackoverflow.com/questions/20900814/…
Ahmad Ali Nasir

24
Nowi czytelnicy: pamiętajcie, że to pytanie zadawano początkowo w okresie beta Android Studio; odpowiedź zmieniała się w czasie. Zwróć uwagę na wersję Gradle wymienioną w odpowiedziach, a także na to, kiedy odpowiedzi zostały faktycznie opublikowane.
Sean Beach

Jeśli coś naprawdę się zmieni, edytuję pytanie, aby przywrócić status
plaisthos

Android Studio 1.3 na kanale canary w pełni obsługuje NDK. Źródła
Vikasdeep Singh

18 czerwca 2015: Android Studio 1.3 Beta jest już dostępne w kanale beta! Przepraszamy, ta kompilacja nie zawiera jeszcze obsługi C / C ++; źródło: tools.android.com/recent/androidstudio13betaavailable
fastr.de

Odpowiedzi:


85

Udostępniliśmy pierwszą wersję integracji jako podgląd w 1.3: http://tools.android.com/tech-docs/android-ndk-preview

Integracja pozostanie podglądem nawet wtedy, gdy wersja 1.3 stanie się ostateczna. Brak aktualnego czasu ETA określającego, kiedy będzie ostateczny (od 2015/07/10).

Więcej informacji tutaj: http://tools.android.com/tech-docs/android-ndk-preview


2
Byłoby wspaniale, gdybym mógł użyć NDK i uzupełniania poleceń z debugowaniem w Android Studio (i obsłudze Gradle)
powder366

1
@GREnvoy - Jak skonfigurować odpowiedniego kreatora NDK w Android Studio? Czy możesz podać mi kroki? :)
Shravan,

7
@DirtyBeach Dlaczego jest nieaktualny? Nadal nie ma integracji NDK w Studio. Pracujemy nad tym, ale w tej chwili nie ma ETA.
Xavier Ducrohet

2
Moje działanie opierało się na tym, jak definiowałem „integrację”. Zrozumiałem to jako „sposób na wykorzystanie NDK z gradle”, który teraz istnieje, aczkolwiek żadne z nich nie jest fantastycznym rozwiązaniem. Jednak na podstawie Twojego komentarza wydaje się, że Twój zespół ma na myśli coś innego, czym mogłaby być prawdziwa integracja. Wycofuję swoje poprzednie oświadczenie.
Sean Beach

2
Integracja NDK została ogłoszona podczas Google IO 2015. Jest dostępna w Android Studio 1.3 (podgląd do pobrania wkrótce. Gdy będzie dostępny, wyślę link).
Cypress Frankenfeld

43

AKTUALIZACJA: Android Studio z obsługą NDK jest już dostępne: http://tools.android.com/tech-docs/android-ndk-preview

Aby zbudować za pomocą skryptu, poniższe rozwiązanie gradle powinno działać:

Używam skryptu kompilacji i dodałem go do mojego pliku (wydaje się, że działa 0.8+): Wydaje się, że jest to odpowiednik poniższego rozwiązania (ale wygląda ładniej w pliku gradle):

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

Kompilacja niestety nie kończy się niepowodzeniem, jeśli katalog nie istnieje lub nie zawiera żadnych .soplików.


5
To już nie działa z nową wersją Android Studio, obejść?
proszek366

@ powder366 Zobacz moją odpowiedź.
Leandros

2
Trochę magii Groovy: tasks.withType(com.android.build.gradle.tasks.PackageApplication) { it.jniFolders = [file("libs")] as Set }. Dziękuję za pomoc!
trnl

Jaka jest procedura dla Androida Studio 0.8.9
Pandiri Deepak

1
@plaisthos Wielkie dzięki za wskazanie właściwego kierunku! Druga linia w skrypcie gradle jni.srcDirs = [] //disable automatic ndk-buildjest bardzo ważna, ponieważ uniemożliwi Android Studio przebudowanie kodu źródłowego C / C ++. Próbowałem to rozgryźć przez dwa dni, aż zobaczyłem twój post i to rozwiązało mój problem. Naprawdę uważam, że kompilacja NDK jest lepsza oddzielnie budowana przez makefile wiersza poleceń Android.mk, a nie przez skrypt gradle, ponieważ C / C ++ było budowane przez Makefile od ponad 40 lat!
tonga

40

Wraz z aktualizacją Android Studio do 1.0, obsługa łańcucha narzędzi NDK znacznie się poprawiła ( uwaga: przeczytaj moje aktualizacje na dole tego postu, aby zobaczyć użycie z nową eksperymentalną wtyczką Gradle i Android Studio 1.5 ).

Android Studio i NDK są wystarczająco dobrze zintegrowane, więc wystarczy utworzyć blok ndk {} w pliku build.gradle swojego modułu i ustawić pliki źródłowe w katalogu (module) / src / main / jni - i jesteś Gotowe!

Koniec z ndk-build z linii poleceń.

O tym wszystkim napisałem w moim poście na blogu tutaj: http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/

Najistotniejsze punkty to:

Musisz wiedzieć o dwóch rzeczach. Domyślnie, jeśli masz zewnętrzne biblioteki, które chcesz załadować do aplikacji na Androida, są one domyślnie wyszukiwane w (module) / src / main / jniLibs. Możesz to zmienić, używając ustawienia sourceSets.main.jniLibs.srcDirs w pliku build.gradle modułu. Będziesz potrzebował podkatalogu z bibliotekami dla każdej docelowej architektury (np. X86, arm, mips, arm64-v8a itp.)

Kod, który chcesz skompilować domyślnie przez łańcuch narzędzi NDK, będzie znajdować się w (module) / src / main / jni i podobnie jak powyżej, możesz go zmienić ustawiając sourceSets.main.jni.srcDirs w pliku build.gradle modułu

i umieść to w pliku build.gradle swojego modułu:

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
}

To jest proces kompilowania kodu w C ++, stamtąd musisz go załadować i utworzyć opakowania - ale sądząc po twoim pytaniu, już wiesz, jak to wszystko zrobić, więc nie będę ponownie haszował.

Umieściłem również repozytorium Github tego przykładu tutaj: http://github.com/sureshjoshi/android-ndk-swig-example

AKTUALIZACJA: 14 czerwca 2015 r

Kiedy pojawi się Android Studio 1.3, powinno być lepsze wsparcie dla C ++ poprzez wtyczkę JetBrains CLion. Obecnie zakładam, że pozwoli to na rozwój Java i C ++ z poziomu Android Studio; jednak myślę, że nadal będziemy musieli używać sekcji Gradle NDK, jak wspomniałem powyżej. Dodatkowo myślę, że nadal będzie potrzeba pisania plików opakowujących Java <-> C ++, chyba że CLion zrobi to automatycznie.

AKTUALIZACJA: 5 stycznia 2016 r

Zaktualizowałem swojego bloga i repozytorium Github (w gałęzi deweloperskiej), aby używać Androida Studio 1.5 z najnowszą eksperymentalną wtyczką Gradle (0.6.0-alpha3).

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

Kompilacja Gradle dla sekcji NDK wygląda teraz następująco:

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
}

Co ciekawe, Android Studio ma funkcję autouzupełniania dla C ++ - otoki generowane przez Javę przy użyciu słowa kluczowego „natywny”:

Przykład autouzupełniania C ++ - opakowanie Java

Jednak nie jest to całkowicie różowe ... Jeśli używasz SWIG do pakowania biblioteki w celu automatycznego generowania kodu, a następnie spróbujesz użyć natywnego automatycznego generowania słowa kluczowego, umieści kod w niewłaściwym miejscu w twoim Swig _wrap Plik .cxx ... Musisz więc przenieść go do bloku „extern C”:

C ++ - opakowanie Java zostało przeniesione do właściwej lokalizacji

AKTUALIZACJA: 15 października 2017 r

Byłbym niedbały, gdybym nie wspomniał, że Android Studio 2.2 i nowsze wersje mają zasadniczo „natywne” (bez kalamburów) wsparcie dla łańcucha narzędzi NDK za pośrednictwem Gradle i CMake. Teraz, kiedy tworzysz nowy projekt, po prostu wybierz obsługę C ++ i gotowe.

Nadal będziesz musiał wygenerować własny kod warstwy JNI lub użyć techniki SWIG, o której wspomniałem powyżej, ale tworzenie szkieletów C ++ w projekcie na Androida jest teraz trywialne.

Zmiany w pliku CMakeLists (w którym umieszczasz swoje pliki źródłowe C ++) zostaną odebrane przez Android Studio i automatycznie przekompilują wszystkie powiązane biblioteki.


1
umieść * .so w (module) / src / main / jniLibs
fawkes

dlaczego NDEBUG jest zawsze ustawiany podczas korzystania z Android Studio, nawet w przypadku kompilacji do debugowania
pt123

35

W Google IO 2015 Google ogłosił pełną integrację NDK w Android Studio 1.3.

Jest teraz poza podglądem i jest dostępny dla wszystkich: https://developer.android.com/studio/projects/add-native-code.html

Stara odpowiedź: Gradle automatycznie wywołuje, ndk-buildjeśli masz jnikatalog w źródłach projektu.

To działa na Android Studio 0.5.9 (wersja kanaryjska).

  1. Pobierz NDK

  2. Albo dodaj ANDROID_NDK_HOME do zmiennych środowiskowych lub dodaj ndk.dir=/path/to/ndkdo swojego local.propertiesprojektu Android Studio. Dzięki temu Android Studio może automatycznie uruchomić ndk.

  3. Pobierz najnowsze przykładowe projekty firmy Gradle aby zobaczyć przykład projektu ndk. (Są na dole strony). Dobry przykładowy projekt to ndkJniLib.

  4. Skopiuj gradle.buildz przykładowych projektów NDK. Będzie wyglądać mniej więcej tak. To gradle.buildtworzy inny apk dla każdej architektury. Musisz wybrać architekturę, którą chcesz, korzystając z build variantspanelu. okienko wariantów budowania

    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
        }
    
    }

Pamiętaj, że spowoduje to zignorowanie plików Android.mk i Application.mk. Aby obejść ten problem, możesz powiedzieć gradle, aby wyłączył wywołanie atuomatic ndk-build, a następnie ręcznie określić katalog dla źródeł 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
}

Ponadto prawdopodobnie będziesz chciał jawnie wywołać ndk-build w swoim skrypcie budowania gradle, ponieważ właśnie wyłączyłeś automatyczne wywołanie.

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

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

Tak. Ale to działa tylko na platformach Unix i jest również ograniczone, jeśli masz bardziej złożoną niż bardzo prostą konfigurację ndk / makefile.
plaisthos

Tak, automatycznie wygeneruje pliki makefile dla ograniczonych rzeczy, które można ustawić w pliku budowania gradle, jednak istnieje obejście. Dodałem to do mojej odpowiedzi.
Cypress Frankenfeld

1
Wywołanie ndk-build będzie działać tylko w wierszu poleceń, a nie w Android Studio.
Cameron Lowell Palmer

Chociaż nie jest to najnowsza odpowiedź, wydaje się, że jest najdokładniejsza. Zwróć szczególną uwagę na krok 3: „Pobierz najnowsze przykładowe projekty Gradle”.
Sean Beach

4
Używam tego hacka zamiast wyłączać src dir, więc mogę edytować pliki c / c ++ w IDEtasks.all { task -> if (task.name.contains('Ndk')) task.enabled = false }
sherpya

23

Znalazłem "gradle 1.11 com.android.tools.build:gradle:0.9.+" obsługuje teraz pre-build ndk, możesz po prostu umieścić * .so w katalogu src / main / jniLibs. podczas budowania gradle zapakuje ndk we właściwe miejsce.

oto mój projekt

Projekt:
| --src
| - | --main
| - | - | --java
| - | - | --jniLibs
| - | - | - | --armeabi
| - | - | - | - | -. so pliki
| --libs
| - | --other.jar


16

Jak na razie (Android Studio v0.8.6) jest to dość proste. Oto kroki, aby utworzyć aplikację typu „Hello world”:

  1. Pobierz Android NDK i umieść folder główny w jakimś rozsądnym miejscu - być może w tej samej lokalizacji co folder SDK.

  2. Dodaj do swojego local.propertiespliku: ndk.dir=<path-to-ndk>

  3. Dodaj następujący kod do pliku build.gradle wewnątrz defaultConfigzamknięcia, zaraz po versionNamewierszu:ndk { moduleName="hello-world" }

  4. W mainkatalogu modułu aplikacji utwórz nowy folder o nazwie jni.

  5. W tym folderze utwórz plik o nazwie hello-world.c, który zobaczysz poniżej.

  6. Patrz przykład Activityponiższy kod na przykład, jak wywołać metodę (czy jest to funkcja?) W 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'])
}

Znajdź tutaj pełny kod źródłowy bardzo podobnej aplikacji (bez NDK).


Robię dokładnie tak, jak poleciłem w moim obecnym projekcie, ale rzeczy NDK nadal nie są budowane. Jakieś pomysły? Wygląda na to, że buduje wszystko inne, ale po prostu pomija jni.
alice.harrison

@NannuoLei dzięki, próbowałem, ale pojawia się problem polegający na tym, że pliki .so nie są generowane. Wszystko inne wydaje się działać, ale kiedy uruchamiam apkg w emulatorze, narzeka, że ​​nie może załadować udostępnionego obiektu.
aaa90210

@ aaa90210 czy twój emulator jest oparty na obrazie x86? Domyślnie NDK po prostu produkować ARMEABI bibliotekę, jeśli chcesz zbudować x86 obrazu można dodać tę linię do Application.mk: APP_ABI: = armeabi x86
Leo obsługuje Monica Cellio

1
zadziałało ze mną. PS: każdy, kto widzi tę odpowiedź, nie zapomnij zmienić Java_me_mattlogan_ndktest_MainActivity_stringFromJNIna własną :)
AbdulMomen عبدالمؤمن

8

Jeśli używasz Uniksa, najnowsza wersja (0.8) dodaje ndk-build. Oto jak to dodać:

android.ndk {
    moduleName "libraw"
}

Oczekuje, że znajdzie JNI w 'src / main / jni', w przeciwnym razie możesz go zdefiniować za pomocą:

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

Od 28 stycznia 2014 r. Z wersją 0.8 kompilacja nie działa w systemie Windows, musisz wyłączyć kompilację za pomocą:

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

1
Czy jest jakaś dokumentacja dotycząca tej funkcji? Nie mogłem znaleźć żadnego. W tej chwili wydaje się, że całkowicie ignoruję mój Android.mk/Application.mk.
plaisthos

Nie znalazłem żadnego. Być może wkradł się do konstrukcji na wpół upieczony. Jestem w systemie Windows, więc mogę tylko potwierdzić, że nie powiodło się przy próbie wywołania skryptu unix ndk-build. Nie byłoby innego powodu, aby to wywoływać, aby zintegrować kompilację natywną w gradle. Czy jesteś w systemie UNIX?
Anthony


faktycznie spodziewa się znaleźć gotowe pliki * .so w jniLibs.srcDirs
Alpine,

Nie zgodziłbym się z tym, że powoduje awarię wywoływania ndk-build, co absolutnie nie jest konieczne, jeśli wymaga wbudowanych bibliotek. Nie mogę potwierdzić, ponieważ nie mam teraz czasu na vm Linux.
Anthony

7

Eleganckie obejście jest pokazane na https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/Z5yWAvCh4h4J .

Zasadniczo tworzysz jar, który zawiera „lib / armeabi / yourlib.so”, a następnie dołączasz go do kompilacji.


Tak. Działa to dobrze tylko wtedy, gdy nie zmieniasz często kodu natywnego. Będziesz musiał dołączyć do repozytorium binarne pliki jar. W przeciwnym razie otrzymasz skrypt kompilacji, który w locie tworzy słoik.
plaisthos

1
Mam zmodyfikowany Witam-JNI przykład Androida z prostego skryptu bash że okłady ndk-build, generuje .jarS dla każdego .soi umieszcza je w ścieżki budowania Gradle do złagodzić ten ból. Sprawdź to.
dbro

4

Dobra odpowiedź, automatyzująca pakowanie łatwo skompilowanych .so-plików, znajduje się w innym (zamkniętym) wątku . Aby to zadziałało, musiałem zmienić linię:

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

w:

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

Bez tej zmiany .sopliki nie zostałyby znalezione, a zatem zadanie ich pakowania nigdy by się nie uruchomiło.


Aktualizacja: należy pamiętać, że w nowszych Android Studios (przynajmniej w wersji 1.5) kod natywny jest znacznie lepiej wbudowany i nie jest konieczne wykonywanie tego oddzielnego zadania w celu spakowania kodu.
HYS

4

Odpowiedź od @plaisthos zepsuła się w najnowszej wersji gradle, ale wciąż jest na to sposób. Stwórznative-libs katalog w katalogu głównym swojego projektu i skopiuj wszystkie nasze biblioteki do tego katalogu.

Dodaj następujące wiersze do pliku build.gradle. Buduj i bądź szczęśliwy.

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

To jest kod, którego używam do budowania za pomocą android-ndk z gradle. W tym celu dodaj ścieżkę do katalogu ndk w gradle.propertiesie. dodawać ndkdir=/home/user/android-ndk-r9di umieścić wszystkie pliki w folderze JNI nativew src/main/jak widać kod pisał poniżej. Utworzy jar z natywnymi bibliotekami, których możesz używać normalnie, jak wSystem.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

Użyłem następującego kodu do skompilowania natywnych bibliotek Dropbox, używam 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

Aby rozwinąć to, co powiedział Naxos (Dzięki Naxos za wysłanie mnie we właściwym kierunku!), Nauczyłem się sporo z niedawno wydanych przykładów NDK i zamieściłem odpowiedź w podobnym pytaniu tutaj.

Jak skonfigurować NDK z wtyczką Android Gradle 0.7

Ten post zawiera szczegółowe informacje na temat łączenia gotowych bibliotek natywnych z aplikacją dla różnych architektur, a także informacje o tym, jak dodać obsługę NDK bezpośrednio do skryptu build.gradle. W większości przypadków nie musisz już wykonywać żadnych czynności związanych z zipem i kopiowaniem.


1

Oto kroki, które wykonałem, aby NDK działał w moim projekcie Android Studio. Użyłem tego samouczka, aby mi pomóc https://software.intel.com/en-us/videos/using-the-ndk-with-android-studio

Aby używać NDK, musisz dodać wiersz NDK do local.properties. Więc pod twoim sdk.dir dodaj

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

W moich aplikacjach build.gradle mam następujący kod

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

nazwa modułu to nazwa, którą chcesz nadać swojemu natywnemu kodowi. Wierzę, że tak będzie się nazywała biblioteka współdzielona. ldLibs pozwala mi zalogować się do LogCat, stl to plik STL, który chcesz zaimportować. Istnieje wiele opcji, takich samych jak Eclipse NDK. ( http://www.kandroid.org/ndk/docs/CPLUSPLUS-SUPPORT.html )

cFlagi to dla mnie nadal pewna ilość czarnej magii. Nie znalazłem dobrego źródła dla wszystkich opcji i tego, co mi dają. Przeszukaj StackOverflow w poszukiwaniu wszystkiego, czego potrzebujesz, to jest tam, gdzie to znalazłem. Wiem, że c ++ 11 pozwala mi używać nowego standardu c ++ 11.

Oto przykład, jak loguję się do LogCat z kodu natywnego

__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

skonfiguruj projekt w android studio z eclipse: musisz zaimportować projekt eclipse ndk do android studio bez eksportowania do gradle i działa, musisz również dodać ścieżkę ndk w local.properties , jeśli wyświetla błąd, dodaj

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

w pliku build.gradle , a następnie utwórz folder jni i plik za pomocą terminala i uruchom go


1
Zobacz, zobacz moją własną odpowiedź. To jest obejście, którego obecnie używam, ale tak naprawdę nie jest to rozwiązanie.
plaisthos

1

Teraz, gdy Android Studio jest w stabilnym kanale, uruchomienie próbek android-ndk jest całkiem proste . Te przykłady używają eksperymentalnej wtyczki ndk i są nowsze niż te, do których linki znajdują się w dokumentacji online systemu Android NDK. Gdy już wiesz, że działają, możesz przestudiować pliki build.gradle, local.properties i gradle-wrapper.properties i odpowiednio zmodyfikować projekt. Oto kroki, które pozwolą im działać.

  1. Przejdź do ustawień, Wygląd i zachowanie, Ustawienia systemu, Android SDK, wybierz kartę Narzędzia SDK i sprawdź Android NDK w wersji 1.0.0 u dołu listy. Spowoduje to pobranie NDK.

  2. Wskaż lokalizację nowo pobranego NDK. Zauważ, że zostanie on umieszczony w katalogu sdk / ndk-bundle. Zrób to, wybierając plik, strukturę projektu, lokalizację zestawu SDK (po lewej) i podając ścieżkę w lokalizacji Android NDK. To doda wpis ndk do local.properties podobny do tego:

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

Z powodzeniem zbudowałem i wdrożyłem wszystkie projekty w repozytorium w ten sposób, z wyjątkiem gles3gni, natywnego kodeka i kreatora. Używam następujących:

Android Studio 1.3 kompilacja AI-141.2117773
próbki android -ndk opublikowane 28 lipca 2015 r. (Link powyżej)
SDK Tools 24.3.3
NDK r10e wyodrębniony do C: \ Android \ sdk \ ndk-bundle Wtyczka
Gradle 2.5
Gradle 0.2.0
Windows 8.1 64 bit


1

NDK Builds i Gradle (podstawowe)

Generalnie budowanie za pomocą NDK jest tak proste, jak prawidłowe określenie ścieżki ndkBuild do Android.mk lub ścieżki cmake do CMakeLists.txt. Polecam CMake zamiast starszego Android.mk, ponieważ obsługa C / C ++ w Android Studio jest oparta na CLion i używa CMake jako formatu projektu. Z mojego doświadczenia wynika, że ​​powoduje to, że IDE jest bardziej responsywne w przypadku większych projektów. Wszystko skompilowane w twoim projekcie zostanie automatycznie zbudowane i skopiowane do 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'])
}

Dodawanie gotowych bibliotek do projektu (zaawansowane)

Biblioteki statyczne (.a) w twojej kompilacji NDK zostaną automatycznie uwzględnione, ale wstępnie skompilowane biblioteki dynamiczne (.so) będą musiały zostać umieszczone w jniLibs. Można to skonfigurować za pomocą sourceSets, ale należy przyjąć standard. NIE POTRZEBUJESZ żadnych dodatkowych poleceń w programiebuild.gradle gdy dołączasz wstępnie skompilowane biblioteki.

Układ jniLibs

Więcej informacji na temat struktury można znaleźć w Podręczniku użytkownika wtyczki Android Gradle .

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

Następnie możesz sprawdzić, czy wynikowy pakiet APK zawiera Twoje pliki .so, zwykle pod build/outputs/apk/, używając unzip -l myApp.apkdo wyświetlenia zawartości.

Budowanie bibliotek współdzielonych

Jeśli tworzysz bibliotekę współdzieloną w NDK, nie musisz nic więcej robić. Zostanie poprawnie dołączony do pakietu APK.


0

Po prostu dodaj te linie do aplikacji 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)
}

Myślę, że podejście jniLibs.srcDirs jest czystsze niż to, ponieważ możesz użyć abiFilter / flavours, ale twoje podejście powinno również działać.
plaisthos

0

teraz mogę załadować taki sukces!

1. dodaj plik .so do tej ścieżki

Project:

| --src | - | --main | - | - | --java | - | - | --jniLibs | - | - | - | --armeabi | - | - | - | - | -. so pliki

2. dodaj ten kod do gradle.build

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

}

3.System.loadLibrary("yousoname");

  1. powodzenia, z gradle 1.2.3 jest ok

0
  1. Jeśli twój projekt został wyeksportowany z eclipse, dodaj poniższe kody w pliku gradle :

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

2.Jeśli tworzysz projekt w Android Studio:

utwórz folder o nazwie jniLibs w src / main / , i umieść swoje pliki * .so w folderze jniLibs.

I skopiuj kod jak poniżej w swoim pliku gradle :

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

0

Chociaż uważam, że SJoshi (wyrocznia) ma najbardziej kompletną odpowiedź, projekt SWIG jest przypadkiem specjalnym, interesującym i użytecznym, ale nie uogólnionym dla większości projektów, które dobrze sobie radziły ze standardowymi projektami opartymi na SDK mrówek. NDK. Wszyscy chcielibyśmy teraz najprawdopodobniej używać Android Studio lub chcieć bardziej przyjaznego dla CI narzędzia do budowania dla urządzeń mobilnych, który teoretycznie oferuje gradle.

Opublikowałem moje podejście, pożyczone skądś (znalazłem to na SO, ale zamieściłem streszczenie aplikacji build.gradle: https://gist.github.com/truedat101/c45ff2b69e91d5c8e9c7962d4b96e841 ). Krótko mówiąc, polecam:

  • Nie aktualizuj swojego projektu do najnowszej wersji Gradle
  • Użyj com.android.tools.build:gradle:1.5.0 w katalogu głównym projektu
  • Użyj com.android.application w projekcie aplikacji
  • Upewnij się, że gradle.properties ma: android.useDeprecatedNdk = true (na wypadek, gdyby narzekał)
  • Skorzystaj z powyższego podejścia, aby zapewnić, że godziny i godziny pracy przy tworzeniu plików Android.mk nie zostaną odrzucone. Ty decydujesz, które cele mają być zbudowane. Te instrukcje są dobre dla użytkowników systemu Windows, którzy teoretycznie powinni być w stanie budować w systemie Windows bez specjalnych problemów.

Gradle na Androida był moim zdaniem bałaganem, ponieważ podobają mi się zapożyczone koncepcje mavena i uparta struktura katalogów dla projektu. Ta funkcja NDK jest „dostępna wkrótce” od prawie 3 lat.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.