Android studio, gradle и NDK
Я очень новичок в этой поддержке gradle и Android Studio. Мне удалось преобразовать мой проект android в gradle с помощью опции экспорта.
но я ищу некоторую документацию или начальную точку, как интегрировать сборку NDK в процесс сборки gradle.
Если возможно, мне также нужен какой-то этап" После", который копирует двоичные файлы сборки (файлы.so) в каталог активов.
23 ответа:
мы выпустили первую версию интеграции в качестве предварительного просмотра в 1.3:http://tools.android.com/tech-docs/android-ndk-preview
интеграция останется предварительным просмотром даже после того, как 1.3 станет окончательным. Нет текущего ETA относительно того, когда он будет окончательным (по состоянию на 2015/07/10).
дополнительная информация здесь:http://tools.android.com/tech-docs/android-ndk-preview
обновление: студия андроида с поддержкой НДК вне теперь: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 toolchain значительно улучшилась (Примечание: пожалуйста, прочитайте мои обновления в нижней части этого сообщения, чтобы увидеть использование с новым экспериментальным плагином Gradle и Android Studio 1.5).
Android Studio и NDK интегрированы достаточно хорошо, так что вам просто нужно создать блок ndk{} в сборке вашего модуля.gradle, и установите исходные файлы в каталог (module)/src/main/jni - и все готово!
нет больше ndk-сборки из командной строки.
Я написал Все об этом в своем блоге здесь:http://www.sureshjoshi.com/mobile/android-ndk-in-android-studio-with-swig/
основные моменты:
есть две вещи, которые нужно знать здесь. По умолчанию, если у вас есть внешние библиотеки, которые вы хотите загрузить в приложение Android, они по умолчанию ищут в (модуле)/src/main/jniLibs. Вы можете измените это с помощью параметра sourceSets.главный.джнилибс.srcDirs в сборке вашего модуля.градля. Вам понадобится подкаталог с библиотеками для каждой архитектуры, на которую вы ориентируетесь (например, x86, arm, mips, arm64-v8a и т. д.)
код, который вы хотите скомпилировать по умолчанию с помощью NDK toolchain, будет расположен в (module)/src/main / jni и, как и выше, вы можете изменить его, установив sourceSets.главный.средой JNI.srcDirs в сборке вашего модуля.gradle
и поставить это в сборка вашего модуля.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
обновление: 14 июня 2015
когда Android Studio 1.3 выходит, там должно быть лучшая поддержка C++ через плагин JetBrains CLion. В настоящее время я предполагаю, что это позволит разрабатывать Java и C++ из Android Studio; однако я думаю, что нам все равно нужно будет использовать раздел Gradle NDK, как я уже говорил выше. Кроме того, я думаю, что по-прежнему будет необходимость писать файлы-оболочки JavaC++, если CLion не будет делать это автоматически.
обновление: 5 января 2016 года
я обновил свой блог и GitHub РЕПО (в разработке филиал) для использования Android Studio 1.5 с последним экспериментальным плагином 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
сборка Gradle для раздела NDK теперь выглядит следующим образом:
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 имеет автозаполнение для C++-Java генерируемых оболочек с использованием "родной" ключевое слово:
однако, это не совсем безоблачно... Если вы используете SWIG для обертывания библиотеки для автоматического создания кода, а затем пытаетесь использовать собственное ключевое слово auto-generation, он поместит код в неправильное место в вашем Swig _wrap.файл CXX... Поэтому вам нужно переместить его в блок "extern C":
обновление: 15 октября 2017
Я был бы неосторожен, если бы не упомянул об этом Android Studio 2.2 и далее имеет по существу "родную" (без каламбура) поддержку NDK toolchain через Gradle и CMake. Теперь, когда вы создаете новый проект, просто выберите поддержку C++, и вы можете идти.
вам все равно нужно будет создать свой собственный код слоя JNI или использовать технику SWIG, о которой я упоминал выше, но леса C++ в проекте Android теперь тривиальны.
изменения в файле CMakeLists (где вы размещаете исходные файлы C++) будут подобраны Android Studio, и он будет автоматически перекомпилировать любые связанные библиотеки.
в Google IO 2015, Google объявила о полной интеграции NDK в Android Studio 1.3.
это теперь из предварительного просмотра, и доступны для всех:https://developer.android.com/studio/projects/add-native-code.html
старый ответ: Gradle автоматически вызывает
ndk-build
Если у вас .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 }
кроме того, вы, вероятно, захотите вызвать ndk-build в своем скрипте сборки gradle явно, потому что вы только что отключили автоматический вызов.
task ndkBuild(type: Exec) { commandLine 'ndk-build', '-C', file('src/main/jni').absolutePath } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild }
Я нашел " gradle 1.11 com.андроид.инструменты.сборка: gradle: 0.9.+ "поддерживает предварительную сборку ndk теперь, вы можете просто поставить*. so в dir src/main / jniLibs. при построении. Gradle будет пакет NDK в правильном месте.
вот мой проект
Project: |--src |--|--main |--|--|--java |--|--|--jniLibs |--|--|--|--armeabi |--|--|--|--|--.so files |--libs |--|--other.jar
Как сказал Ксавье, вы можете поместить свои предварительные сборки в /src / main/ jniLibs / если вы используете gradle 0.7.2+
взято из: https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/ctDp9viWaxoJ
на данный момент (Android Studio v0.8.6) это довольно просто. Вот шаги, чтобы создать приложение типа "Hello world":
загрузите Android NDK и поместите корневую папку где-нибудь в здравом уме-в том же месте, что и папка SDK, возможно.
добавьте следующее к вашему :
ndk.dir=<path-to-ndk>
добавьте в свою сборку следующее.gradle файл внутри
defaultConfig
закрытие, сразу послеversionName
линия:ndk { moduleName="hello-world" }
в модуле вашего приложения создайте новую папку под названием
jni
.в этой папке создайте файл с именем
hello-world.c
, который вы увидите ниже.пример
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).
Если вы находитесь на unix последняя версия (0.8) добавляет ndk-build. Вот как его добавить:
android.ndk { moduleName "libraw" }
он ожидает найти JNI под 'src / main/jni', в противном случае вы можете определить его с помощью:
sourceSets.main { jni.srcDirs = 'path' }
по состоянию на 28 января 2014 года с версией 0.8 сборка разбита на windows, вы должны отключить сборку с:
sourceSets.main { jni.srcDirs = [] //disable automatic ndk-build call (currently broken for windows) }
элегантный обходной путь показан в https://groups.google.com/d/msg/adt-dev/nQobKd2Gl_8/Z5yWAvCh4h4J.
в основном вы создаете банку, которая содержит "lib/armeabi / yourlib.so", а затем включаете банку в сборку.
хороший ответ автоматизация упаковки легко составленному
.so
- файлы даны в другой (закрытой) темы. Чтобы заставить это работать, мне пришлось изменить строку:from fileTree(dir: 'libs', include: '**/*.so')
в:
from fileTree(dir: 'src/main/libs', include: '**/*.so')
без этого изменения
.so
файлы не были найдены, и поэтому задача их упаковки никогда не будет выполняться.
ответ от @plaisthos сломался в последней версии gradle, но все еще есть способ сделать это. Создайте
native-libs
каталог в корневом каталоге вашего проекта и скопируйте все наши библиотеки в этот каталог.добавьте следующие строки в свою сборку.градля. Стройте и будьте счастливы.
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'
это код, который я использую для создания с помощью android-ndk от gradle. Для этого добавьте путь к каталогу ndk в
gradle.properties
ie . добавитьndkdir=/home/user/android-ndk-r9d
и поместите все файлы jni в папкуnative
наsrc/main/
как вы можете видеть из кода размещены ниже. Он создаст банку с родными библиотеками, которые вы можете использовать нормально, как в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'
я использовал следующий код для компиляции собственных библиотек 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) }
я использовал
ndk.dir=/usr/shareData/android-ndk-r11b
/ / путь ndk
на местные.свойства файл в проекте android studio. и добавьте эту строку :android.useDeprecatedNdk=true
на gradle.свойства файл в проекте android studio.
Более подробная информация здесь: http://tools.android.com/tech-docs/android-ndk-preview
об этом заявил Наксос (Наксос Спасибо за отправку меня в правильном направлении!), Я узнал совсем немного из недавно выпущенных примеров NDK и опубликовал ответ на аналогичный вопрос здесь.
как настроить NDK с Android Gradle плагин 0.7
Это сообщение содержит полную информацию о связывании готовых собственных библиотек в ваше приложение для различных архитектур, а также информацию о том, как добавить поддержку NDK непосредственно в сборку.Gradle в скрипт. По большей части, вам больше не нужно делать работу вокруг zip и копировать.
вот шаги, которые я использовал, чтобы заставить NDK работать в моем проекте Android Studio. Я использовал этот учебник, чтобы помочь мне https://software.intel.com/en-us/videos/using-the-ndk-with-android-studio
для использования NDK необходимо добавить строку NDK в local.свойства. Так что под вашим sdk.реж добавить
ndk.dir=C\:\MyPathToMyNDK\ndk
в моих приложениях сборки.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());
настройки проекта в Android-студия из eclipse: вы должны импортировать проект eclipse ndk в Android studio без экспорта в gradle, и он работает , также вам нужно добавить путь ndk в местные.свойства ,Если показывает ошибку, то добавить
sourceSets.main { jniLibs.srcDir 'src/main/libs' jni.srcDirs = [] //disable automatic ndk-build callenter code here }
in построить.gradle затем создать jni папка и файл с помощью терминала и запустить его будет работать
теперь, когда Android Studio находится в стабильном канале, довольно просто получить андроид-НДК образцов работает. Эти образцы используют экспериментальный плагин ndk и новее, чем те, которые связаны с онлайн-документацией Android NDK. Как только вы узнаете, что они работают, вы можете изучить сборку.Gradle, а местные.свойства и gradle-обертка.файлы свойств и соответствующим образом измените свой проект. Ниже приведены шаги, чтобы получить их рабочий.
перейдите в Настройки, Внешний вид и поведение, Системные настройки, Android SDK, выберите вкладку SDK Tools и проверьте Android NDK версии 1.0.0 в нижней части списка. Это позволит загрузить NDK.
укажите местоположение вновь загруженного NDK. Обратите внимание, что он будет помещен в каталог sdk/ndk-bundle. Для этого выберите Файл, структуру проекта, расположение SDK (слева) и укажите путь в разделе расположение Android NDK. Это добавит запись ndk в local.свойства, подобные этому:
Mac / Linux: ndk.dir= / Android / sdk / NDK-bundle
Окна: НДК.dir=C:\Android\sdk\NDK-bundleЯ успешно построил и развернул все проекты в репозитории таким образом, за исключением gles3gni, native-codec и builder. Я использую следующее:
Android Studio 1.3 build AI-141.2117773
Android-NDK образцы опубликованы 28 июля, 2015 (ссылка выше)
SDK Tools 24.3.3
НДК р10э извлеченный к C:\Android\sdk\ndk-bundle
Gradle 2.5
Gradle плагин 0.2.0
ОС Windows 8.1 64 бит
NDK строит и gradle (basic)
как правило, построение с помощью NDK так же просто, как правильно указать путь ndkBuild к Android.mk или путь cmake к CMakeLists.формат txt. Я рекомендую 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']) }
добавление готовых библиотек в проект (дополнительно)
статические библиотеки (.a) в вашей сборке NDK будет автоматически включен, но предварительно построенные динамические библиотеки (.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.
просто добавьте эти строки в приложение
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) }
сейчас.Я могу загрузить так успех!
1.добавить .так что файл по этому пути
Project:
/ --src |--|--главный |--|--|--ява |-- / -- / --jniLibs |--|--|--|--норм |--|--|--|--|--.так что файлы
2.добавьте этот код в gradle.строй
android { splits { abi { enable true reset() include 'x86', 'x86_64', 'arm64-v8a', 'armeabi-v7a', 'armeabi' universalApk false } }
}
3.
System.loadLibrary("yousoname");
- goodluck для вас, это нормально с gradle 1.2.3
если ваш проект экспортируется из eclipse, добавьте коды ниже в файл gradle:
android { sourceSets{ main{ jniLibs.srcDir['libs'] } } }
2.Если вы создаете проект в Android studio:
создайте папку с именем jniLibs в src/ main / ,и поместите ваши файлы *.so в папку jniLibs.
и скопируйте код, как показано ниже в вашем файле gradle :
android { sourceSets{ main{ jniLibs.srcDir['jniLibs'] } } }
хотя я считаю, что SJoshi (oracle guy) имеет наиболее полный ответ, проект SWIG является частным случаем, интересным и полезным, но не обобщенным для большинства проектов, которые хорошо справились со стандартными проектами на основе SDK ant + NDK. Мы все хотели бы использовать Android studio сейчас, скорее всего, или хотите более CI дружественной сборки toolchain для мобильных устройств, которые gradle теоретически предлагает.
Я опубликовал свой подход, заимствованный откуда-то (я нашел это так, но суть для сборки приложения.gradle:https://gist.github.com/truedat101/c45ff2b69e91d5c8e9c7962d4b96e841). В двух словах, я рекомендую следующее:
- Не обновляйте свой проект до последней сборки gradle
- использовать com.андроид.инструменты.сборка: gradle: 1.5.0 в корне вашего проекта
- использовать com.андроид.применение в вашем проекте приложения
- убедитесь, что gradle.свойства: андроид.useDeprecatedNdk=true (в случае, если это жалуюсь)
- используйте вышеуказанный подход, чтобы гарантировать, что ваши часы и часы усилий создания Android.mk файлы не будут выброшены. Вы управляете тем, какие цели арки(ы) построить. И эти инструкции добры к пользователям Windows, которые теоретически должны иметь возможность строить на windows без особых проблем.
Gradle для Android был беспорядок на мой взгляд, так как мне нравятся заимствованные концепции maven и самоуверенная структура каталогов для проекта. Эта функция NDK была "скоро" в течение почти 3+ лет.