Android
Gradle для Android
Поиск…
Вступление
Gradle - это система сборки на основе JVM, которая позволяет разработчикам писать высокоуровневые сценарии, которые могут использоваться для автоматизации процесса компиляции и создания приложений. Это гибкая система на основе плагинов, которая позволяет автоматизировать различные аспекты процесса сборки; включая компиляцию и .jar
, загрузку и управление внешними зависимостями, ввод полей в AndroidManifest
или использование определенных версий SDK.
Синтаксис
apply plugin
: плагины, которые обычно должны использоваться только'com.android.application'
или'com.android.library'
.android
: основная конфигурация вашего приложения-
compileSdkVersion
: скомпилированная версия SDK -
buildToolsVersion
: версия инструмента сборки -
defaultConfig
: настройки по умолчанию, которые могут быть перезаписаны вкусами и типами сборки-
applicationId
: идентификатор приложения, который вы используете, например, в PlayStore, в основном совпадает с именем вашего пакета -
minSdkVersion
: минимальная требуемая версия SDK -
targetSdkVersion
: SDK-версия, с которой вы компилируете (всегда должна быть новая) -
versionCode
: внутренний номер версии, который должен быть больше при каждом обновлении -
versionName
: номер версии, которую пользователь может видеть на странице сведений о приложении
-
-
buildTypes
: см. где-то еще (TODO)
-
dependencies
: maven или локальные зависимости вашего приложения-
compile
одну зависимость -
testCompile
: зависимость для модульных или интеграционных тестов
-
замечания
Смотрите также
- Официальная страница gradle
- Как настроить градиентные сборки
- Плагин android для градиента
- Android Gradle DSL
Gradle for Android - Расширенная документация:
Существует еще один тег, где вы можете найти больше тем и примеров использования градиента в Android.
http://www.riptutorial.com/topic/2092
Базовый файл build.gradle
Это пример файла build.gradle
умолчанию в модуле.
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion '25.0.3'
signingConfigs {
applicationName {
keyAlias 'applicationName'
keyPassword 'password'
storeFile file('../key/applicationName.jks')
storePassword 'keystorePassword'
}
}
defaultConfig {
applicationId 'com.company.applicationName'
minSdkVersion 14
targetSdkVersion 25
versionCode 1
versionName '1.0'
signingConfig signingConfigs.applicationName
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
testCompile 'junit:junit:4.12'
}
DSL (язык, специфичный для домена)
Каждый блок в указанном выше файле называется DSL
(специфичным для домена языком).
Плагины
В первой строке apply plugin: 'com.android.application'
, применяет плагин Android для Gradle к сборке и блокирует блок android {}
для объявления вариантов сборки для Android.
Для Android-приложения :
apply plugin: 'com.android.application'
Для Android-библиотеки :
apply plugin: 'com.android.library'
Понимание DSL в приведенном выше образце
Вторая часть, блок android {...}
- это Android DSL
который содержит информацию о вашем проекте.
Например, вы можете установить compileSdkVersion
который определяет уровень API Android, который должен использоваться Gradle для компиляции вашего приложения.
В defaultConfig
содержатся значения по умолчанию для вашего манифеста. Вы можете override
их с помощью продуктов Flavors .
Вы можете найти больше информации в этих примерах:
зависимости
Блок dependencies
определяется вне блока android
{...}
: это означает, что он не определен плагином Android, но это стандартный Gradle.
Блок dependencies
определяет, какие внешние библиотеки (как правило, библиотеки Android, но библиотеки Java также действительны), которые вы хотите включить в свое приложение. Gradle автоматически загрузит эти зависимости для вас (если локальная копия отсутствует), вам просто нужно добавить похожие строки compile
если вы хотите добавить другую библиотеку.
Давайте посмотрим на одну из представленных здесь строк:
compile 'com.android.support:design:25.3.1'
Эта строка в основном говорит
добавьте зависимость от библиотеки дизайна поддержки Android к моему проекту.
Gradle гарантирует, что библиотека будет загружена и представлена, чтобы вы могли использовать ее в своем приложении, а ее код также будет включен в ваше приложение.
Если вы знакомы с Maven, этот синтаксис - это GroupId , двоеточие, ArtifactId , другой двоеточие, а затем версия зависимости, которую вы хотите включить, что дает вам полный контроль над версиями.
Хотя можно указать версии артефакта, используя знак плюса (+), лучше всего избегать этого; это может привести к проблемам, если библиотека будет обновлена с нарушением изменений без вашего ведома, что, вероятно, приведет к сбоям в вашем приложении.
Вы можете добавить различные зависимости:
Особое внимание должно быть уделено плоской зависимости aar .
Вы можете найти более подробную информацию в этой теме.
Обратите внимание на -v7 в appcompat-v7
compile 'com.android.support:appcompat-v7:25.3.1'
Это просто означает, что эта библиотека ( appcompat
) совместима с уровнем API Android 7 и appcompat
.
Примечание о junit: junit: 4.12
Это тестовая зависимость для модульного тестирования.
Указание зависимостей, характерных для разных конфигураций компоновки
Вы можете указать, что зависимость должна использоваться только для определенной конфигурации сборки или вы можете определить различные зависимости для типов сборки или продуктов (например, отладка, тестирование или выпуск) с помощью debugCompile
, testCompile
или releaseCompile
вместо обычного compile
,
Это полезно для хранения зависимостей, связанных с тестированием и отладкой, из вашей сборки релиза, что позволит вашей версии APK
как можно более тонкой и поможет гарантировать, что любая информация об отладке не может использоваться для получения внутренней информации о вашем приложении.
signingConfig
signingConfig
позволяет вам настроить Gradle для включения информации о keystore
и убедиться, что APK, построенный с использованием этих конфигураций, подписан и готов к выпуску Play Store.
Здесь вы можете найти специальную тему .
Примечание . Не рекомендуется сохранять учетные данные подписи в вашем файле Gradle. Чтобы удалить настройки подписи, просто опустите часть signingConfigs
.
Вы можете указать их по-разному:
- сохранение во внешнем файле
- сохраняя их при настройке переменных среды .
См. Эту тему для получения более подробной информации: Подпишите APK без раскрытия пароля хранилища ключей .
Вы можете найти дополнительную информацию о Gradle для Android в теме Gradle .
Определение вкусов продукта
build.gradle
продукта определены в файле build.gradle
внутри блока android { ... }
как показано ниже.
...
android {
...
productFlavors {
free {
applicationId "com.example.app.free"
versionName "1.0-free"
}
paid {
applicationId "com.example.app.paid"
versionName "1.0-paid"
}
}
}
Делая это, у нас теперь есть два дополнительных продукта: free
и paid
. Каждый из них может иметь свою собственную конфигурацию и атрибуты. Например, оба наших новых вкуса имеют отдельное имя applicationId
и versionName
чем наш существующий main
аромат (доступный по умолчанию, поэтому не показан здесь).
Добавление зависимых от продукта вкусовых зависимостей
Зависимости могут быть добавлены для конкретного вкуса продукта , аналогично тому, как они могут быть добавлены для конкретных конфигураций сборки.
В этом примере предположим, что мы уже определили два продукта, называемых free
и paid
(подробнее об определении вкусов здесь ).
Затем мы можем добавить зависимость AdMob для free
аромата и библиотеку Picasso для paid
например:
android {
...
productFlavors {
free {
applicationId "com.example.app.free"
versionName "1.0-free"
}
paid {
applicationId "com.example.app.paid"
versionName "1.0-paid"
}
}
}
...
dependencies {
...
// Add AdMob only for free flavor
freeCompile 'com.android.support:appcompat-v7:23.1.1'
freeCompile 'com.google.android.gms:play-services-ads:8.4.0'
freeCompile 'com.android.support:support-v4:23.1.1'
// Add picasso only for paid flavor
paidCompile 'com.squareup.picasso:picasso:2.5.2'
}
...
Добавление ресурсов, специфичных для продукта
Ресурсы могут быть добавлены для конкретного продукта .
В этом примере предположим, что мы уже определили два продукта, называемых free
и paid
. Чтобы добавить ресурсы, специфичные для продукта, мы создаем дополнительные папки ресурсов вместе с папкой main/res
, которые затем можно добавить к ресурсам, как обычно. В этом примере мы определим строку, status
, для каждого продукта:
/ src / main /res/values/strings.xml
<resources>
<string name="status">Default</string>
</resources>
/ src / free /res/values/strings.xml
<resources>
<string name="status">Free</string>
</resources>
/ src / paid /res/values/strings.xml
<resources>
<string name="status">Paid</string>
</resources>
Строки status
специфичные для вкуса продукта, переопределяют значение status
в main
ароматизаторе.
Определение и использование полей конфигурации сборки
BuildConfigField
Gradle позволяет buildConfigField
определять константы. Эти константы будут доступны во время выполнения в качестве статических полей класса BuildConfig
. Это можно использовать для создания ароматов , определяя все поля в блоке defaultConfig
, а затем переопределяя их для отдельных defaultConfig
сборки по мере необходимости.
В этом примере определяется дата сборки и флаги сборки для производства, а не теста:
android {
...
defaultConfig {
...
// defining the build date
buildConfigField "long", "BUILD_DATE", System.currentTimeMillis() + "L"
// define whether this build is a production build
buildConfigField "boolean", "IS_PRODUCTION", "false"
// note that to define a string you need to escape it
buildConfigField "String", "API_KEY", "\"my_api_key\""
}
productFlavors {
prod {
// override the productive flag for the flavor "prod"
buildConfigField "boolean", "IS_PRODUCTION", "true"
resValue 'string', 'app_name', 'My App Name'
}
dev {
// inherit default fields
resValue 'string', 'app_name', 'My App Name - Dev'
}
}
}
Автоматически созданное <имя_пакета>. BuildConfig
.java в папке gen содержит следующие поля на основе указанной выше директивы:
public class BuildConfig {
// ... other generated fields ...
public static final long BUILD_DATE = 1469504547000L;
public static final boolean IS_PRODUCTION = false;
public static final String API_KEY = "my_api_key";
}
Определенные поля теперь можно использовать в приложении во время выполнения, BuildConfig
к сгенерированному классу BuildConfig
:
public void example() {
// format the build date
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
String buildDate = dateFormat.format(new Date(BuildConfig.BUILD_DATE));
Log.d("build date", buildDate);
// do something depending whether this is a productive build
if (BuildConfig.IS_PRODUCTION) {
connectToProductionApiEndpoint();
} else {
connectToStagingApiEndpoint();
}
}
ResValue
resValue
в productFlavors
создает значение ресурса. Это может быть любой тип ресурсов ( string
, dimen
, color
и т. Д.). Это похоже на определение ресурса в соответствующем файле: например, определение строки в файле strings.xml
. Преимущество состоит в том, что тот, который определен в градиенте, может быть изменен на основе вашего productFlavor / buildVariant. Чтобы получить доступ к значению, напишите тот же код, как если бы вы получали доступ к res из файла ресурсов:
getResources().getString(R.string.app_name)
Важно то, что ресурсы, определенные таким образом, не могут изменять существующие ресурсы, определенные в файлах. Они могут создавать только новые значения ресурсов.
Некоторым библиотекам (например, API Android для Google Maps) требуется ключ API, указанный в манифесте в качестве тега meta-data
. Если для отладочной и производственной сборки нужны разные ключи, укажите манифест заполнителя, заполненный Gradle.
В вашем файле AndroidManifest.xml
:
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="${MAPS_API_KEY}"/>
Затем установите соответствующее поле в файле build.gradle
:
android {
defaultConfig {
...
// Your development key
manifestPlaceholders = [ MAPS_API_KEY: "AIza..." ]
}
productFlavors {
prod {
// Your production key
manifestPlaceholders = [ MAPS_API_KEY: "AIza..." ]
}
}
}
Система сборки Android автоматически генерирует несколько полей и помещает их в BuildConfig.java
. Эти поля:
поле | Описание |
---|---|
DEBUG | Boolean сообщение, если приложение находится в режиме отладки или выпуска |
APPLICATION_ID | String содержащая идентификатор приложения (например, com.example.app ) |
BUILD_TYPE | String содержащая тип сборки приложения (обычно либо debug либо release ) |
FLAVOR | String содержащая особый аромат сборки |
VERSION_CODE | int содержащий номер версии (сборки). Это то же самое , как versionCode в build.gradle или versionCode в AndroidManifest.xml |
VERSION_NAME | String содержащая имя версии (сборки). Это то же самое , как versionName в build.gradle или versionName в AndroidManifest.xml |
В дополнение к вышесказанному, если вы определили несколько параметров вкуса, то каждое измерение будет иметь свое значение. Например, если у вас есть два размера аромата для color
и size
вас также будут следующие переменные:
поле | Описание |
---|---|
FLAVOR_color | String содержащая значение для цветового оттенка. |
FLAVOR_size | String содержащая значение для аромата размера. |
Централизация зависимостей через файл «dependencies.gradle»
При работе с многомодульными проектами полезно централизовать зависимости в одном месте, а не распространять их во многих файлах сборки, особенно для обычных библиотек, таких как библиотеки поддержки Android и библиотеки Firebase .
Одним из рекомендуемых способов является разделение файлов сборки Gradle с одним build.gradle
на модуль, а также с одним в корне проекта и другим для зависимостей, например:
root
+- gradleScript/
| dependencies.gradle
+- module1/
| build.gradle
+- module2/
| build.gradle
+- build.gradle
Затем все ваши зависимости могут быть расположены в gradleScript/dependencies.gradle
:
ext {
// Version
supportVersion = '24.1.0'
// Support Libraries dependencies
supportDependencies = [
design: "com.android.support:design:${supportVersion}",
recyclerView: "com.android.support:recyclerview-v7:${supportVersion}",
cardView: "com.android.support:cardview-v7:${supportVersion}",
appCompat: "com.android.support:appcompat-v7:${supportVersion}",
supportAnnotation: "com.android.support:support-annotations:${supportVersion}",
]
firebaseVersion = '9.2.0';
firebaseDependencies = [
core: "com.google.firebase:firebase-core:${firebaseVersion}",
database: "com.google.firebase:firebase-database:${firebaseVersion}",
storage: "com.google.firebase:firebase-storage:${firebaseVersion}",
crash: "com.google.firebase:firebase-crash:${firebaseVersion}",
auth: "com.google.firebase:firebase-auth:${firebaseVersion}",
messaging: "com.google.firebase:firebase-messaging:${firebaseVersion}",
remoteConfig: "com.google.firebase:firebase-config:${firebaseVersion}",
invites: "com.google.firebase:firebase-invites:${firebaseVersion}",
adMod: "com.google.firebase:firebase-ads:${firebaseVersion}",
appIndexing: "com.google.android.gms:play-services-appindexing:${firebaseVersion}",
];
}
Который может быть применен из этого файла в файле верхнего уровня build.gradle
следующим образом:
// Load dependencies
apply from: 'gradleScript/dependencies.gradle'
и в module1/build.gradle
:
// Module build file
dependencies {
// ...
compile supportDependencies.appCompat
compile supportDependencies.design
compile firebaseDependencies.crash
}
Другой подход
Менее подробный подход для централизации версий зависимостей библиотек может быть достигнут путем объявления номера версии как переменной один раз и использования ее повсюду.
В рабочей области root build.gradle
добавьте следующее:
ext.v = [
supportVersion:'24.1.1',
]
И в каждом модуле, который использует одну и ту же библиотеку, добавьте необходимые библиотеки
compile "com.android.support:support-v4:${v.supportVersion}"
compile "com.android.support:recyclerview-v7:${v.supportVersion}"
compile "com.android.support:design:${v.supportVersion}"
compile "com.android.support:support-annotations:${v.supportVersion}"
Структура каталогов для ресурсов, специфичных для вкуса
Различные варианты создания приложений могут содержать разные ресурсы. Чтобы создать ресурс, специфичный для вкуса, создайте каталог с наименьшим именем вашего аромата в каталоге src
и добавьте свои ресурсы таким же образом, как вы обычно.
Например, если у вас есть аромат Development
и вы хотите предоставить отдельный значок запуска, вы должны создать каталог src/development/res/drawable-mdpi
а внутри этого каталога создайте файл ic_launcher.png
с вашим значком, зависящим от конкретной разработки.
Структура каталогов будет выглядеть так:
src/
main/
res/
drawable-mdpi/
ic_launcher.png <-- the default launcher icon
development/
res/
drawable-mdpi/
ic_launcher.png <-- the launcher icon used when the product flavor is 'Development'
(Конечно, в этом случае вы также создадите значки для drawable-hdpi, drawable-xhdpi и т . Д. ).
Почему в проекте Android Studio есть два файла build.gradle?
<PROJECT_ROOT>\app\build.gradle
специфичен для модуля приложения .
<PROJECT_ROOT>\build.gradle
- это «файл сборки верхнего уровня», где вы можете добавить параметры конфигурации, общие для всех подпроектов / модулей.
Если вы используете другой модуль в своем проекте, в качестве локальной библиотеки у вас будет другой файл build.gradle
: <PROJECT_ROOT>\module\build.gradle
В файле верхнего уровня вы можете указать общие свойства как блок buildscript или некоторые общие свойства.
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.google.gms:google-services:3.0.0'
}
}
ext {
compileSdkVersion = 23
buildToolsVersion = "23.0.1"
}
В app\build.gradle
вы определяете только свойства для модуля:
apply plugin: 'com.android.application'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
}
dependencies {
//.....
}
Выполнение скрипта оболочки из градиента
Сценарий оболочки - это очень универсальный способ расширить вашу сборку до практически всего, что вы можете придумать.
В качестве примера, вот простой скрипт для компиляции файлов protobuf и добавления результирующих java-файлов в исходный каталог для дальнейшей компиляции:
def compilePb() {
exec {
// NOTICE: gradle will fail if there's an error in the protoc file...
executable "../pbScript.sh"
}
}
project.afterEvaluate {
compilePb()
}
Сценарий оболочки «pbScript.sh» для этого примера, расположенный в корневой папке проекта:
#!/usr/bin/env bash
pp=/home/myself/my/proto
/usr/local/bin/protoc -I=$pp \
--java_out=./src/main/java \
--proto_path=$pp \
$pp/my.proto \
--proto_path=$pp \
$pp/my_other.proto
Отладка ошибок Gradle
Ниже приведена отрывок из Gradle. Что такое ненулевое значение выхода и как его исправить? , см. его для полного обсуждения.
Предположим, вы разрабатываете приложение, и вы получаете некоторую ошибку Gradle, которая появляется, как правило, будет выглядеть так.
:module:someTask FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':module:someTask'.
> some message here... finished with non-zero exit value X
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: Y.ZZ secs
Вы ищете здесь, в StackOverflow, для своей проблемы, и люди говорят, чтобы очистить и перестроить ваш проект, или включить MultiDex , и когда вы попробуете это, это просто не устраняет проблему.
Есть способы получить дополнительную информацию , но сам вывод Gradle должен указывать на фактическую ошибку в нескольких строках над этим сообщением между: module:someTask FAILED
и последним :module:someOtherTask
который прошел. Поэтому, если вы зададите вопрос о своей ошибке, отредактируйте свои вопросы, чтобы включить больше контекста в ошибку.
Таким образом, вы получаете «ненулевое значение выхода». Ну, это число является хорошим показателем того, что вы должны попытаться исправить. Вот несколько наиболее часто встречающихся случаев.
-
1
является просто общим кодом ошибки, и ошибка, скорее всего, в выходе Gradle -
2
похоже, связано с перекрывающимися зависимостями или неправильной конфигурацией проекта. -
3
похоже, связано со слишком большим количеством зависимостей или проблемой памяти.
Общие решения для вышеизложенного (после попытки «Очистить и перестроить проект»):
-
1
- Обратите внимание на указанную ошибку. Как правило, это ошибка времени компиляции, то есть некоторая часть кода в вашем проекте недопустима. Это включает в себя как XML, так и Java для Android-проекта. -
2
и3
- Многие ответы здесь дают вам возможность включить multidex . Хотя это может решить проблему, это, скорее всего, обходной путь. Если вы не понимаете, почему вы его используете (см. Ссылку), вам, вероятно, это не понадобится. Общие решения включают в себя сокращение чрезмерного использования зависимостей библиотек (например, от всех сервисов Google Play, когда вам нужно использовать только одну библиотеку, например, Карты или Вход в систему).
Указание различных идентификаторов приложений для типов и типов продуктов
Вы можете указать разные идентификаторы приложений или имена пакетов для каждого типа buildType
или productFlavor
используя атрибут конфигурации applicationIdSuffix :
Пример суффикса applicationId
для каждого типа buildType
:
defaultConfig {
applicationId "com.package.android"
minSdkVersion 17
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
debuggable false
}
development {
debuggable true
applicationIdSuffix ".dev"
}
testing {
debuggable true
applicationIdSuffix ".qa"
}
}
В результате мы applicationIds
:
- com.package.android для
release
- com.package.android. dev для
development
- com.package.android. qa для
testing
Это можно сделать и для productFlavors
:
productFlavors {
free {
applicationIdSuffix ".free"
}
paid {
applicationIdSuffix ".paid"
}
}
Результирующее applicationIds
будет:
- com.package.android. бесплатно для
free
вкуса - com.package.android. заплатил за
paid
аромат
Подписать APK без раскрытия пароля хранилища ключей
Вы можете определить конфигурацию подписи, чтобы подписать apk в файле build.gradle
используя следующие свойства:
-
storeFile
: файл хранилища ключей -
storePassword
: пароль хранилища ключей -
keyAlias
: ключевое имя псевдонима -
keyPassword
: пароль псевдонима ключа
Во многих случаях вам может потребоваться избежать такой информации в файле build.gradle
.
Способ A: Настроить подпись выпуска с помощью файла keystore.properties.
Можно сконфигурировать build.gradle
вашего приложения, чтобы он считывал вашу информацию о настройке build.gradle
из файла свойств, такого как keystore.properties
.
Настройка подписи так же выгодна, потому что:
- Ваша информация о настройке
build.gradle
отделена от файлаbuild.gradle
- Вам не нужно вмешиваться во время процесса подписания, чтобы предоставить пароли для файла хранилища ключей
- Вы можете легко исключить файл
keystore.properties
из управления версиями
Во-первых, создайте файл с именем keystore.properties
в корневом каталоге вашего проекта с таким содержимым (заменив значения собственными):
storeFile=keystore.jks
storePassword=storePassword
keyAlias=keyAlias
keyPassword=keyPassword
Теперь в файле build.gradle
вашего приложения signingConfigs
блок signingConfigs
следующим образом:
android {
...
signingConfigs {
release {
def propsFile = rootProject.file('keystore.properties')
if (propsFile.exists()) {
def props = new Properties()
props.load(new FileInputStream(propsFile))
storeFile = file(props['storeFile'])
storePassword = props['storePassword']
keyAlias = props['keyAlias']
keyPassword = props['keyPassword']
}
}
}
}
Это действительно все, что нужно, но не забудьте исключить как ваш файл keystore.properties
файл keystore.properties
из управления версиями .
Несколько вещей, чтобы отметить:
-
storeFile
путь , указанный вkeystore.properties
файл должен быть относительно вашего приложенияbuild.gradle
файла. В этом примере предполагается, что файл хранилища ключей находится в том же каталоге, что и файлbuild.gradle
приложения. - В этом примере файл
keystore.properties
в корне проекта. Если вы поместите его в другое место, обязательно измените значение вrootProject.file('keystore.properties')
на ваше местоположение по отношению к корню вашего проекта.
Метод B: используя переменную окружения
То же самое можно сделать и без файла свойств, что затрудняет поиск пароля:
android {
signingConfigs {
release {
storeFile file('/your/keystore/location/key')
keyAlias 'your_alias'
String ps = System.getenv("ps")
if (ps == null) {
throw new GradleException('missing ps env variable')
}
keyPassword ps
storePassword ps
}
}
Переменная среды "ps"
может быть глобальной, но более безопасный подход может заключаться в добавлении ее в оболочку Android Studio.
В linux это можно сделать, отредактировав Desktop Entry
Studio Desktop Entry
Exec=sh -c "export ps=myPassword123 ; /path/to/studio.sh"
Вы можете найти более подробную информацию в этой теме .
Версии ваших сборников через файл «version.properties»
Вы можете использовать Gradle для автоматического увеличения вашей версии пакета каждый раз, когда вы его создаете. Для этого создайте файл version.properties
в том же каталоге, что и ваш build.gradle
со следующим содержимым:
VERSION_MAJOR=0
VERSION_MINOR=1
VERSION_BUILD=1
(Изменение значений для основного и второстепенного, как вы сочтете нужным). Затем в build.gradle
добавьте следующий код в раздел android
:
// Read version information from local file and increment as appropriate
def versionPropsFile = file('version.properties')
if (versionPropsFile.canRead()) {
def Properties versionProps = new Properties()
versionProps.load(new FileInputStream(versionPropsFile))
def versionMajor = versionProps['VERSION_MAJOR'].toInteger()
def versionMinor = versionProps['VERSION_MINOR'].toInteger()
def versionBuild = versionProps['VERSION_BUILD'].toInteger() + 1
// Update the build number in the local file
versionProps['VERSION_BUILD'] = versionBuild.toString()
versionProps.store(versionPropsFile.newWriter(), null)
defaultConfig {
versionCode versionBuild
versionName "${versionMajor}.${versionMinor}." + String.format("%05d", versionBuild)
}
}
Информацию можно получить в Java в виде строки BuildConfig.VERSION_NAME
для полного {major}. { BuildConfig.VERSION_NAME
}. {Build} числа и как целое BuildConfig.VERSION_CODE
только для номера сборки.
Изменение имени файла apk и добавление имени версии:
Это код для изменения имени файла прикладного приложения (.apk). Имя можно настроить, присвоив другому значению newName
android {
applicationVariants.all { variant ->
def newName = "ApkName";
variant.outputs.each { output ->
def apk = output.outputFile;
newName += "-v" + defaultConfig.versionName;
if (variant.buildType.name == "release") {
newName += "-release.apk";
} else {
newName += ".apk";
}
if (!output.zipAlign) {
newName = newName.replace(".apk", "-unaligned.apk");
}
output.outputFile = new File(apk.parentFile, newName);
logger.info("INFO: Set outputFile to "
+ output.outputFile
+ " for [" + output.name + "]");
}
}
}
Отключить сжатие изображения для меньшего размера файла APK
Если вы оптимизируете все изображения вручную, отключите APT Cruncher для меньшего размера файла APK.
android {
aaptOptions {
cruncherEnabled = false
}
}
Включить Proguard с помощью gradle
Для включения конфигураций Proguard для вашего приложения вам необходимо включить его в файл уровня градиента на уровне модуля. Вы должны установить значение minifyEnabled
true
.
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Вышеприведенный код применит ваши конфигурации Proguard, содержащиеся в стандартном Android SDK в сочетании с файлом «proguard-rules.pro» на вашем модуле, в ваш выпущенный apk.
Включить поддержку экспериментального NDK-плагина для Gradle и AndroidStudio
Включите и настройте экспериментальный плагин Gradle для улучшения поддержки NDK AndroidStudio. Убедитесь, что вы выполняете следующие требования:
- Gradle 2.10 (для этого примера)
- Android NDK r10 или новее
- Android SDK с инструментами построения v19.0.0 или новее
Настроить файл MyApp / build.gradle
Отредактируйте строку dependencies.classpath в файле build.gradle, например
classpath 'com.android.tools.build:gradle:2.1.2'
в
classpath 'com.android.tools.build:gradle-experimental:0.7.2'
(v0.7.2 была последней версией на момент написания. Проверьте последнюю версию самостоятельно и соответствующим образом адаптируйте свою линию)
Файл build.gradle должен выглядеть примерно так:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.7.2'
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Настроить файл MyApp / app / build.gradle
Отредактируйте файл build.gradle, чтобы он выглядел примерно так, как показано в следующем примере. Номера версий могут отличаться.
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion 19
buildToolsVersion "24.0.1"
defaultConfig {
applicationId "com.example.mydomain.myapp"
minSdkVersion.apiLevel 19
targetSdkVersion.apiLevel 19
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles.add(file('proguard-android.txt'))
}
}
ndk {
moduleName "myLib"
/* The following lines are examples of a some optional flags that
you may set to configure your build environment
*/
cppFlags.add("-I${file("path/to/my/includes/dir")}".toString())
cppFlags.add("-std=c++11")
ldLibs.addAll(['log', 'm'])
stl = "c++_static"
abiFilters.add("armeabi-v7a")
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
Синхронизируйте и проверьте, нет ли ошибок в файлах Gradle перед продолжением.
Проверить, включен ли плагин
Сначала убедитесь, что вы загрузили модуль Android NDK. Затем создайте новое приложение в AndroidStudio и добавьте следующее в файл ActivityMain:
public class MainActivity implements Activity {
onCreate() {
// Pregenerated code. Not important here
}
static {
System.loadLibrary("myLib");
}
public static native String getString();
}
Часть getString()
должна быть выделена красным цветом, говоря, что соответствующая функция JNI не найдена. Наведите указатель мыши на вызов функции, пока не появится красная лампочка. Щелкните лампу и выберите create function JNI_...
Это должно сгенерировать файл myLib.c в каталоге myApp / app / src / main / jni с правильным вызовом функции JNI. Он должен выглядеть примерно так:
#include <jni.h>
JNIEXPORT jstring JNICALL
Java_com_example_mydomain_myapp_MainActivity_getString(JNIEnv *env, jobject instance)
{
// TODO
return (*env)->NewStringUTF(env, returnValue);
}
Если это не так, то плагин не был настроен правильно или NDK не был загружен
Показать все задачи проекта gradle
gradlew tasks -- show all tasks
Android tasks
-------------
androidDependencies - Displays the Android dependencies of the project.
signingReport - Displays the signing info for each variant.
sourceSets - Prints out all the source sets defined in this project.
Build tasks
-----------
assemble - Assembles all variants of all applications and secondary packages.
assembleAndroidTest - Assembles all the Test applications.
assembleDebug - Assembles all Debug builds.
assembleRelease - Assembles all Release builds.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
compileDebugAndroidTestSources
compileDebugSources
compileDebugUnitTestSources
compileReleaseSources
compileReleaseUnitTestSources
extractDebugAnnotations - Extracts Android annotations for the debug variant into the archive file
extractReleaseAnnotations - Extracts Android annotations for the release variant into the archive file
jar - Assembles a jar archive containing the main classes.
mockableAndroidJar - Creates a version of android.jar that's suitable for unit tests.
testClasses - Assembles test classes.
Build Setup tasks
-----------------
init - Initializes a new Gradle build. [incubating]
wrapper - Generates Gradle wrapper files. [incubating]
Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the main source code.
Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'LeitnerBoxPro'.
components - Displays the components produced by root project 'LeitnerBoxPro'. [incubating]
dependencies - Displays all dependencies declared in root project 'LeitnerBoxPro'.
dependencyInsight - Displays the insight into a specific dependency in root project 'LeitnerBoxPro'.
help - Displays a help message.
model - Displays the configuration model of root project 'LeitnerBoxPro'. [incubating]
projects - Displays the sub-projects of root project 'LeitnerBoxPro'.
properties - Displays the properties of root project 'LeitnerBoxPro'.
tasks - Displays the tasks runnable from root project 'LeitnerBoxPro' (some of the displayed tasks may belong to subprojects)
.
Install tasks
-------------
installDebug - Installs the Debug build.
installDebugAndroidTest - Installs the android (on device) tests for the Debug build.
uninstallAll - Uninstall all applications.
uninstallDebug - Uninstalls the Debug build.
uninstallDebugAndroidTest - Uninstalls the android (on device) tests for the Debug build.
uninstallRelease - Uninstalls the Release build.
Verification tasks
------------------
check - Runs all checks.
connectedAndroidTest - Installs and runs instrumentation tests for all flavors on connected devices.
connectedCheck - Runs all device checks on currently connected devices.
connectedDebugAndroidTest - Installs and runs the tests for debug on connected devices.
deviceAndroidTest - Installs and runs instrumentation tests using all Device Providers.
deviceCheck - Runs all device checks using Device Providers and Test Servers.
lint - Runs lint on all variants.
lintDebug - Runs lint on the Debug build.
lintRelease - Runs lint on the Release build.
test - Run unit tests for all variants.
testDebugUnitTest - Run unit tests for the debug build.
testReleaseUnitTest - Run unit tests for the release build.
Other tasks
-----------
assembleDefault
clean
jarDebugClasses
jarReleaseClasses
transformResourcesWithMergeJavaResForDebugUnitTest
transformResourcesWithMergeJavaResForReleaseUnitTest
Немедленно удалить «неприглаженный» apk
Если вам не нужны автоматически сгенерированные файлы apk с unaligned
суффиксом (которого вы, вероятно, нет), вы можете добавить следующий код для файла build.gradle
:
// delete unaligned files
android.applicationVariants.all { variant ->
variant.assemble.doLast {
variant.outputs.each { output ->
println "aligned " + output.outputFile
println "unaligned " + output.packageApplication.outputFile
File unaligned = output.packageApplication.outputFile;
File aligned = output.outputFile
if (!unaligned.getName().equalsIgnoreCase(aligned.getName())) {
println "deleting " + unaligned.getName()
unaligned.delete()
}
}
}
}
Игнорирование варианта сборки
По некоторым причинам вы можете игнорировать свои варианты сборки. Например: у вас есть «макет» вкуса продукта, и вы используете его только для целей отладки, таких как тестирование единиц / контрольно-измерительных приборов.
Давайте проигнорируем вариант mockRelease из нашего проекта. Откройте файл build.gradle и напишите:
// Remove mockRelease as it's not needed.
android.variantFilter { variant ->
if (variant.buildType.name.equals('release') && variant.getFlavors().get(0).name.equals('mock')) {
variant.setIgnore(true);
}
}
Просмотр дерева зависимостей
Используйте зависимости задачи. В зависимости от того, как настроены ваши модули, это могут быть ./gradlew dependencies
или посмотреть зависимости использования приложения модуля ./gradlew :app:dependencies
Пример, следующий за файлом build.gradle
dependencies {
compile 'com.android.support:design:23.2.1'
compile 'com.android.support:cardview-v7:23.1.1'
compile 'com.google.android.gms:play-services:6.5.87'
}
будет отображать следующий график:
Parallel execution is an incubating feature.
:app:dependencies
------------------------------------------------------------
Project :app
------------------------------------------------------------
. . .
_releaseApk - ## Internal use, do not manually configure ##
+--- com.android.support:design:23.2.1
| +--- com.android.support:support-v4:23.2.1
| | \--- com.android.support:support-annotations:23.2.1
| +--- com.android.support:appcompat-v7:23.2.1
| | +--- com.android.support:support-v4:23.2.1 (*)
| | +--- com.android.support:animated-vector-drawable:23.2.1
| | | \--- com.android.support:support-vector-drawable:23.2.1
| | | \--- com.android.support:support-v4:23.2.1 (*)
| | \--- com.android.support:support-vector-drawable:23.2.1 (*)
| \--- com.android.support:recyclerview-v7:23.2.1
| +--- com.android.support:support-v4:23.2.1 (*)
| \--- com.android.support:support-annotations:23.2.1
+--- com.android.support:cardview-v7:23.1.1
\--- com.google.android.gms:play-services:6.5.87
\--- com.android.support:support-v4:21.0.0 -> 23.2.1 (*)
. . .
Здесь вы можете увидеть, что проект напрямую включает в себя com.android.support:design
версию 23.2.1, которая сама приносит com.android.support:support-v4
с версией 23.2.1. Однако com.google.android.gms:play-services
самих com.google.android.gms:play-services
есть зависимость от той же support-v4
но с более старой версией 21.0.0, которая является конфликтом, обнаруженным методом gradle.
(*)
используются, когда gradle пропускает поддерево, потому что эти зависимости уже были указаны ранее.
Используйте gradle.properties для центральной версии номера / buildconfigurations
Вы можете определить центральную конфигурационную информацию в
- отдельный град включает файл. Централизация зависимостей через файл «dependencies.gradle»
- автономный файл свойств Версии ваших сборников через файл «version.properties»
или сделать это с корневым файлом gradle.properties
структура проекта
root
+- module1/
| build.gradle
+- module2/
| build.gradle
+- build.gradle
+- gradle.properties
глобальная настройка для всех подмодулей в gradle.properties
# used for manifest
# todo increment for every release
appVersionCode=19
appVersionName=0.5.2.160726
# android tools settings
appCompileSdkVersion=23
appBuildToolsVersion=23.0.2
использование в подмодуле
apply plugin: 'com.android.application'
android {
// appXXX are defined in gradle.properties
compileSdkVersion = Integer.valueOf(appCompileSdkVersion)
buildToolsVersion = appBuildToolsVersion
defaultConfig {
// appXXX are defined in gradle.properties
versionCode = Long.valueOf(appVersionCode)
versionName = appVersionName
}
}
dependencies {
...
}
Примечание. Если вы хотите опубликовать свое приложение в магазине приложений F-Droid, вы должны использовать магические числа в файле gradle, потому что еще один робот f-droid не может читать текущую версию nnnner для обнаружения / проверки изменений версии.
Отображение информации о подписке
В некоторых случаях (например, при получении ключа API Google) вам нужно найти отпечаток своего хранилища ключей. У Gradle есть удобная задача, отображающая всю информацию о подписке, включая отпечатки ключей:
./gradlew signingReport
Это примерный результат:
:app:signingReport
Variant: release
Config: none
----------
Variant: debug
Config: debug
Store: /Users/user/.android/debug.keystore
Alias: AndroidDebugKey
MD5: 25:08:76:A9:7C:0C:19:35:99:02:7B:00:AA:1E:49:CA
SHA1: 26:BE:89:58:00:8C:5A:7D:A3:A9:D3:60:4A:30:53:7A:3D:4E:05:55
Valid until: Saturday 18 June 2044
----------
Variant: debugAndroidTest
Config: debug
Store: /Users/user/.android/debug.keystore
Alias: AndroidDebugKey
MD5: 25:08:76:A9:7C:0C:19:35:99:02:7B:00:AA:1E:49:CA
SHA1: 26:BE:89:58:00:8C:5A:7D:A3:A9:D3:60:4A:30:53:7A:3D:4E:05:55
Valid until: Saturday 18 June 2044
----------
Variant: debugUnitTest
Config: debug
Store: /Users/user/.android/debug.keystore
Alias: AndroidDebugKey
MD5: 25:08:76:A9:7C:0C:19:35:99:02:7B:00:AA:1E:49:CA
SHA1: 26:BE:89:58:00:8C:5A:7D:A3:A9:D3:60:4A:30:53:7A:3D:4E:05:55
Valid until: Saturday 18 June 2044
----------
Variant: releaseUnitTest
Config: none
----------
Определение типов сборки
Вы можете создавать и настраивать типы сборки в файле build.gradle
уровне build.gradle
внутри блока android {}
.
android { ... defaultConfig {...} buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { applicationIdSuffix ".debug" } } }