...

среда, 26 марта 2014 г.

[Перевод] Интеграция Android Studio, Gradle и NDK

В свете недавних изменений (начиная с релиза 0.7.3 от 27 декабря 2013) новая система сборки под Android становится очень интересной в том числе и для тех, кто использует NDK. Теперь стало действительно просто интегрировать нативные библиотеки в вашу сборку и генерировать APK для различных архитектур, корректно обращаясь с кодами версий.



Интегрируем .so файлы в APK




Если вы используете Android Studio, то для интеграции нативных библиотек в приложение раньше было необходимо применение различных сложных способов, включая maven и пакеты .aar/.jar … Хорошая новость состоит в том, что теперь этого уже не требуется.


Вам только требуется положить .so библиотеки в каталог jniLibs в поддиректории, названные соответственно каждой поддерживаемой ABI (x86, mips, armeabi-v7a, armeabi) – и всё! Теперь все файлы .so будут интегрированы в APK во время сборки:



Если название папки jniLibs вас не устраивает, вы можете задать другое расположение в build.gradle:



android {
...
sourceSets.main {
jniLibs.srcDir 'src/main/libs'
}
}


Строим один APK на архитектуру и добиваемся успеха!




Построить один APK на архитектуру очень просто с использованием свойства abiFilter.

По умолчанию ndk.abiFilter(s) имеет значение all. Это свойство оказывает влияние на интеграцию .so файлов, а также на обращения к ndk-build (мы поговорим об этом в конце поста).

Давайте внесем некоторые архитектурные особенности (конфигурации) в build.gradle:

android{
...
productFlavors {
x86 {
ndk {
abiFilter "x86"
}
}
mips {
ndk {
abiFilter "mips"
}
}
armv7 {
ndk {
abiFilter "armeabi-v7a"
}
}
arm {
ndk {
abiFilter "armeabi"
}
}
fat
}
}




А затем синхронизируем проект с файлами gradle:


Теперь вы можете наслаждаться новыми возможностями, выбирая желаемые варианты сборки:



Каждый из этих вариантов даст вам APK для выбранной архитектуры:



Полный (Release|Debug) APK будет все еще содержать все библиотеки, как и стандартный пакет, упомянутый в начале этого поста.


Но не прекращайте читать на этом месте! Архитектурно-зависимые APK удобны при разработке, но если вы хотите залить несколько из них в Google Play Store, вам необходимо установить различный versionCode для каждого. Сделать это с помощью новейшей системы сборки очень просто.


Автоматически устанавливаем различные коды версий для ABI-зависимых APK




Свойство android.defaultConfig.versionCode отвечает за versionCode для вашего приложения. По умолчанию оно установлено в -1 и, если вы не измените это значение, будет использован versionCode, указанный в файле AndroidManifest.xml.

Поскольку мы хотим динамически изменять наш versionCode, сначала необходимо указать его внутри build.gradle:

android {
...
defaultConfig{
versionName "1.1.0"
versionCode 110
}
}




Однако все еще возможно хранить эту переменную в AndroidManifest.xml, если вы получаете ее «вручную» перед изменением:

import java.util.regex.Pattern

android {
...
defaultConfig{
versionCode getVersionCodeFromManifest()
}
...
}

def getVersionCodeFromManifest() {
def manifestFile = file(android.sourceSets.main.manifest.srcFile)
def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
def matcher = pattern.matcher(manifestFile.getText())
matcher.find()
return Integer.parseInt(matcher.group(1))
}




Теперь вы можете использовать versionCode с различными модификаторами:

android {
...
productFlavors {
x86 {
versionCode Integer.parseInt("6" + defaultConfig.versionCode)
ndk {
abiFilter "x86"
}
}
mips {
versionCode Integer.parseInt("4" + defaultConfig.versionCode)
ndk {
abiFilter "mips"
}
}
armv7 {
versionCode Integer.parseInt("2" + defaultConfig.versionCode)
ndk {
abiFilter "armeabi-v7a"
}
}
arm {
versionCode Integer.parseInt("1" + defaultConfig.versionCode)
ndk {
abiFilter "armeabi"
}
}
fat
}
}




Здесь мы поставили префикс 6 для x86, 4 для mips, 2 для ARMv7 и 1 для ARMv5.

Работа с ndk в Android Studio




Если в исходниках проекта есть папка jni, система сборки попытается вызвать ndk-build автоматически.

В текущей реализации ваши Android.mk мейкфайлы игнорируются, вместо них создается новый на лету. Это действительно удобно для небольших проектов (вам больше вообще не требуются .mk файлы!), но в больших может раздражать, если вам требуются все возможности, предоставляемые мейкфайлами. Существует возможность отключить это свойство в build.gradle:

android{
...
sourceSets.main.jni.srcDirs = [] //disable automatic ndk-build call
}




Если вы хотите использовать генерируемый на лету мейкфайл, вы можете настроить его изначально, установив свойство ndk.moduleName, например, так:

android {
...
defaultConfig {
ndk {
moduleName "hello-jni"
}
}
}




Вы также можете установить другие свойства ndk:


  • cFlags,

  • ldLibs,

  • stl (т.е.: gnustl_shared, stlport_static …),

  • abiFilters (т.е.: «x86», «armeabi-v7a»).




Генерация отладочного APK достигается заданием значения true для свойства android.buildTypes.debug.jniDebugBuild; в этом случае ndk-build будет передано NDK_DEBUG=1.

Если вы используете RenderScript из NDK, вам потребуется установить значение true для свойства defaultConfig.renderscriptNdkMode.

Если вы доверяете авто-генерируемым мейкфайлам, то можете задавать различные cFlags в зависимости от конечной архитектуры, когда вы собираете многоархитектурные APK. Так что если вы хотите полностью довериться gradle, мы рекомендуем генерировать различные APK для архитектур, используя ранее описанные модификаторы конфигурации:

...
productFlavors {
x86 {
versionCode Integer.parseInt("6" + defaultConfig.versionCode)
ndk {
cFlags cFlags + " -mtune=atom -mssse3 -mfpmath=sse"
abiFilter "x86"
}
}
...


Мой пример файла .gradle




Соединяя все вместе, привожу файл build.gradle, который сам сейчас использую. В нем нет модификаторов для различных поддерживаемых ABI, он не использует интеграцию с ndk-build, поэтому работает в Windows окружении и не требует ни изменения обычных мест расположения исходников и библиотек, ни содержимого моих .mk файлов.

import java.util.regex.Pattern

buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.9.0'
}
}

apply plugin: 'android'

android {
compileSdkVersion 19
buildToolsVersion "19.0.3"

defaultConfig{
versionCode getVersionCodeFromManifest()
}

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

productFlavors {
x86 {
versionCode Integer.parseInt("6" + defaultConfig.versionCode)
ndk {
abiFilter "x86"
}
}
mips {
versionCode Integer.parseInt("4" + defaultConfig.versionCode)
ndk {
abiFilter "mips"
}
}
armv7 {
versionCode Integer.parseInt("2" + defaultConfig.versionCode)
ndk {
abiFilter "armeabi-v7a"
}
}
arm {
versionCode Integer.parseInt("1" + defaultConfig.versionCode)
ndk {
abiFilter "armeabi"
}
}
fat
}
}

def getVersionCodeFromManifest() {
def manifestFile = file(android.sourceSets.main.manifest.srcFile)
def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
def matcher = pattern.matcher(manifestFile.getText())
matcher.find()
return Integer.parseInt(matcher.group(1))
}


Устранение неисправностей




NDK не сконфигурирован



Если вы получаете ошибку:

Execution failed for task ':app:compileX86ReleaseNdk'.
> NDK not configured




Это означает, что инструменты не найдены в каталоге NDK. Имеется два выхода: установить переменную ANDROID_NDK_HOME в соответствии с вашим каталогом NDK и удалить local.properties или же установить ее вручную внутри local.properties:

ndk.dir=C\:\\Android\\ndk




Не существует правила для создания цели



Если вы получаете ошибку:

make.exe: *** No rule to make target ...\src\main\jni




Ее причиной может быть имеющаяся ошибка в NDK для Windows, когда имеется только один исходный файл для компилирования. Добавьте еще один пустой файл – и все заработает.
Прочие вопросы



Вы, возможно, сможете найти ответы на интересующие вас вопросы в google группе adt-dev.

Получение информации по интеграции NDK




Лучшее место для нахождения более подробной информации – официальная страница проекта.

Посмотрите на список изменений и, если пролистаете его целиком, найдете примеры проектов, связанных с интеграцией NDK, внутри самых свежих архивов gradle-samples-XXX.zip.

На видео ниже показано, как настроить проект с исходниками NDK из Android Studio.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий