SlideShare a Scribd company logo
1 of 52
Download to read offline
Plugin for plugin, 
or extending 
Android New Build System 
Anton Rutkevich
About me 
› 4+ years of Android development 
› Mobile game-dev experience 
› At Yandex: 
1. Mobile Yandex.Metrica 
2. Continuous Integration
Не удается отобразить рисунок. Возможно, рисунок 
поврежден или недостаточно памяти для его открытия. 
Перезагрузите компьютер, а затем снова откройте файл. 
Если вместо рисунка все еще отображается красный 
крестик, попробуйте удалить рисунок и вставить его 
заново. 
Why do I need this? 
Intro
What can be done? 
› Additional resources/code/manifest processing 
› Output processing (apk, aar, jar) 
› Other things
Story 
Prod / test 
servers 
Flavors! 
LoTgesst o /n /poroffd 
AaUndnasil qyotunice/s bo uffi ld 
numb...e r! 
I want to 
configure it 
myself! 
2 Flav3o rs! 
FlaHvmorms?.. . 
Manager Android dev
How should it work 
Java code build.gradle Teamcity 
Actual value: 
"https://my.server.com" 
CI server can do it 
Our job
Insert CI value into BuildConfig.java 
// app/build.gradle 
apply plugin: 'com.android.application' 
android {" 
defaultConfig { 
buildConfigField "String", "URL", ""${teamcity['server-url']}"" 
buildConfigField "String", "URL", ""#server-url"" 
}" 
} 
project.teamcity = [ 
"server-url" : "https://my.server.com" 
// ..." 
] 
url']}"".
Use BuildConfig.java from Java 
public class SomeJavaClass { 
" 
// ... 
public static final String SERVER_URL = "https://my.server.com"; 
public static final String SERVER_URL = BuildConfig.URL; 
// ... 
}
BuildConfig placeholder plugin 
› Replaces placeholder values with values from some map 
› Map can come from anywhere
Goal 
// app/build.gradle 
apply plugin: 'com.android.application' 
apply plugin: 'placeholder' 
" 
placeholder {" 
replacements = project.teamcity 
} 
android {" 
defaultConfig {" 
buildConfigField "String", "URL", ""#server-url""" 
}" 
}
Table of contents 
› Gradle basics 
› New Build System workflow 
› Hello, Gradle plugin! 
› Extending Android New Build System
Не удается отобразить рисунок. Возможно, рисунок 
поврежден или недостаточно памяти для его открытия. 
Перезагрузите компьютер, а затем снова откройте файл. 
Если вместо рисунка все еще отображается красный 
крестик, попробуйте удалить рисунок и вставить его 
заново. 
Tools we will use 
Gradle basics
Plugins everywhere 
NBS
Tasks 
› Can be configured with { } 
› Consist of actions 
› Can depend on other tasks 
› Can have inputs / outputs
Task consists of actions 
Task 
Action Action 
Action Action 
doFirst() doLast(), or <<
Tasks execution order 
Task 2 
Task 3 
Task 4 
dependsOn 
dependsOn 
dependsOn 
Execution order 
Task 1 
Task 2 Task 3 Task 4 Task 1
Outputs 
Task inputs / outputs 
Inputs Task 
Inputs & outputs did not change 
=> 
UP-TO-DATE
Task example 
task myTask { 
ext.myMessage = "hello" 
} 
myTask << { 
println myMessage 
} 
task otherTask(dependsOn: myTask)
Task example output 
>> gradle otherTask 
:app:myTask 
hello 
:app:otherTask
Build lifecycle 
settings.gradle 
build.gradle 
Initialization Configuration Execution 
Projects creation 
Projects 
configuration 
Tasks creation 
Tasks configuration 
project.afterEvaluate { } 
Task graph execution 
Task graph 
Build initialization
The New Build System 
workflow 
Не удается отобразить рисунок. Возможно, рисунок 
поврежден или недостаточно памяти для его открытия. 
Перезагрузите компьютер, а затем снова откройте файл. 
Если вместо рисунка все еще отображается красный 
крестик, попробуйте удалить рисунок и вставить его 
заново. 
What's so special?
What tasks will be launched? 
build 
check assemble 
assembleDebug assembleRelease 
Guaranteed assemble<VariantName>
Android project build overview
Tasks we will need 
assemble<VariantName> 
.... 
generate<VariantName>BuildConfig 
.... 
compile<VariantName>Java 
....
Variant API 
Source code 
is your documentation! 
› Access to most variant's tasks 
› Variant output related properties 
› Different for apps & libraries
Hello, Gradle plugin! 
Не удается отобразить рисунок. Возможно, рисунок 
поврежден или недостаточно памяти для его открытия. 
Перезагрузите компьютер, а затем снова откройте файл. 
Если вместо рисунка все еще отображается красный 
крестик, попробуйте удалить рисунок и вставить его 
заново. 
The first steps
The very basic one 
src/main/groovy/com/example/gradle/PlaceholderPlugin.gradle 
public class PlaceholderPlugin implements Plugin<Project> { 
@Override" 
void apply(Project project) { 
project.task('hello') << {" 
println "Hello Gradle plugin!" 
} 
} 
}
Bind plugin class to plugin name 
src/main/resources/META-INF/gradle-plugins/placeholder.properties 
implementation-class=com.example.gradle.PlaceholderPlugin
Extension 
Extension
Add extension 
src/main/groovy/com/example/gradle/PlaceholderExtension.gradle 
class PlaceholderExtension {" 
def replacements = [:] 
}"
Add extension 
@Override" 
void apply(Project project) {" 
PlaceholderExtension extension = project.extensions.create(" 
"placeholder", PlaceholderExtension" 
); 
project.task('hello') << { 
println "Hello Gradle plugin!" 
println "Hi, ${project.placeholder.replacements}" 
} 
}"
Use extension 
// app/build.gradle 
apply plugin: 'placeholder'" 
" 
placeholder {" 
replacements = ["server-url" : "https://my.server.com"] 
}" 
--------------------------------------------- 
>> gradle hello 
:app:hello" 
Hi, [server-url:https://my.server.com]
Extending 
The New Build System 
Не удается отобразить рисунок. Возможно, рисунок 
поврежден или недостаточно памяти для его открытия. 
Перезагрузите компьютер, а затем снова откройте файл. 
Если вместо рисунка все еще отображается красный 
крестик, попробуйте удалить рисунок и вставить его 
заново. 
Let's do it!
Check for New Build System 
// PlaceholderPlugin.groovy 
@Override" 
void apply(Project project) { 
if (project.hasProperty("android")) { 
PlaceholderExtension extension = project.extensions.create(" 
"placeholder", PlaceholderExtension" 
); 
def android = project.android 
// all code goes here 
} 
}"
Let the New Build System do its job 
// PlaceholderPlugin.apply() 
if (project.hasProperty("android")) { 
PlaceholderExtension extension = project.extensions.create(" 
"placeholder", PlaceholderExtension" 
); 
def android = project.android 
project.afterEvaluate {" 
// at this point we have all 
// tasks from New Build System 
} 
}
Process every variant 
// PlaceholderPlugin.apply() 
project.afterEvaluate { 
if (android.hasProperty('applicationVariants')) { 
android.applicationVariants.all { variant -> 
addActions(project, variant, extension) 
} 
} else if (android.hasProperty('libraryVariants')) { 
android.libraryVariants.all { variant -> 
addActions(project, variant, extension) 
} 
} 
}
Add task 
// PlaceholderPlugin.groovy 
def addActions(Project project, variant, 
PlaceholderExtension extension) { 
Task processPlaceholders = project.task( 
"process${variant.name.capitalize()}Placeholders" 
) 
processPlaceholders << { 
println "I will replace ${variant.name}!" 
} 
}
Insert task into build process 
assemble<VariantName> 
.... 
generate<VariantName>BuildConfig 
.... 
process<VariantName>Placeholders 
compile<VariantName>Java 
....
Insert task into build process 
// PlaceholderPlugin.groovy 
def addActions(Project project, variant, 
PlaceholderExtension extension) { 
Task processPlaceholders = ... 
... 
variant.javaCompile.dependsOn processPlaceholders" 
processPlaceholders.dependsOn variant.generateBuildConfig 
}
Does it really work? 
>> gradle assembleDebug 
:app:preBuild 
... 
:app:generateDebugBuildConfig 
... 
:app:processDebugPlaceholders 
I will replace debug! 
:app:compileDebugJava 
...
Actual work. Perform replacements 
// PlaceholderPlugin.addActions() 
processPlaceholders << { 
def buildConfigFile = getBuildConfig(variant) 
" 
extension.replacements.each { replacement ->" 
project.ant.replace(" 
file: buildConfigFile," 
token: "#${replacement.key}", 
value: replacement.value" 
)" 
} 
}
Handling inputs / outputs 
process 
Placeholders 
BuildConfig.java 
BuildConfig.java 
BuildConfig.java 
replacements 
generate 
BuildConfig 
... 
replacements 
<< Action
Replace task with 'doLast' 
// PlaceholderPlugin.addActions() 
processPlaceholders << { 
variant.generateBuildConfig << { 
def buildConfigFile = ... 
extension.replacements.each { ... } 
} 
variant.generateBuildConfig.inputs.property( 
"replacements", extension.replacements 
)
│ We've done it!
Remember how to use it? 
// app/build.gradle 
apply plugin: 'com.android.application'" 
apply plugin: 'placeholder'" 
" 
placeholder {" 
replacements = project.teamcity 
}" 
" 
android {" 
defaultConfig {" 
buildConfigField "String", "URL", ""#server-url""" 
}" 
}
Does it work? 
app/build/generated/source/buildConfig/debug/com/example/ 
sample/BuildConfig.java 
public final class BuildConfig {" 
// Fields from default config." 
public static final String URL = "https://my.server.com"; 
}
Не удается отобразить рисунок. Возможно, рисунок 
поврежден или недостаточно памяти для его открытия. 
Перезагрузите компьютер, а затем снова откройте файл. 
Если вместо рисунка все еще отображается красный 
крестик, попробуйте удалить рисунок и вставить его 
заново. 
To summarize
Key steps 
› Create Gradle plugin 
› Inside afterEvaluate { } 
› Process every variant 
› Add action to generateBuildConfig 
› Handle inputs / outputs
What's next? 
› Default values support 
› Errors handling 
› Publish ( jcenter / mavenCentral / other )
Links 
Gradle 
http://www.gradle.org/ 
The New Build System 
http://tools.android.com/tech-docs/new-build-system 
http://tools.android.com/tech-docs/new-build-system/build-workflow 
Github sample 
https://github.com/roottony/android-placeholder-plugin
Thank you for your attention! 
Anton Rutkevich 
Senior software engineer 
antonrut@yandex-team.ru 
anton.rutkevich@gmail.com

More Related Content

What's hot

Alexander manuhin selenium_php_v2.0
Alexander manuhin selenium_php_v2.0Alexander manuhin selenium_php_v2.0
Alexander manuhin selenium_php_v2.0matroskin1980
 
Тестируй это / Виктор Русакович (GP Solutions)
Тестируй это / Виктор Русакович (GP Solutions)Тестируй это / Виктор Русакович (GP Solutions)
Тестируй это / Виктор Русакович (GP Solutions)Ontico
 
Самодельная параметризация и параллелизация тестов на Webdriver (JS)
Самодельная параметризация и параллелизация тестов на Webdriver (JS) Самодельная параметризация и параллелизация тестов на Webdriver (JS)
Самодельная параметризация и параллелизация тестов на Webdriver (JS) COMAQA.BY
 
Особенности разработки API / Всеволод Шмыров (Яндекс)
Особенности разработки API / Всеволод Шмыров (Яндекс)Особенности разработки API / Всеволод Шмыров (Яндекс)
Особенности разработки API / Всеволод Шмыров (Яндекс)Ontico
 
Превышаем скоросные лимиты с Angular 2
Превышаем скоросные лимиты с Angular 2Превышаем скоросные лимиты с Angular 2
Превышаем скоросные лимиты с Angular 2Oleksii Okhrymenko
 
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшeQA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшeQAFest
 
Behat в PHP с использованием Behat и Mink
Behat в PHP с использованием Behat и MinkBehat в PHP с использованием Behat и Mink
Behat в PHP с использованием Behat и Minktyomo4ka
 
Превышаем скоростные лимиты с Angular 2
Превышаем скоростные лимиты с Angular 2Превышаем скоростные лимиты с Angular 2
Превышаем скоростные лимиты с Angular 2Oleksii Okhrymenko
 
Drupal Camp Kyiv 2013. Удобная разработка drupal проекта. Полезные модули.
Drupal Camp Kyiv 2013. Удобная разработка drupal проекта. Полезные модули.Drupal Camp Kyiv 2013. Удобная разработка drupal проекта. Полезные модули.
Drupal Camp Kyiv 2013. Удобная разработка drupal проекта. Полезные модули.Alex Barkov
 
FPUG Dzyga presentation
FPUG Dzyga presentationFPUG Dzyga presentation
FPUG Dzyga presentationIvan Filimonov
 
Pycon Russia 2013 - Разработка через тестирование в Python и Django
Pycon Russia 2013 - Разработка через тестирование в Python и DjangoPycon Russia 2013 - Разработка через тестирование в Python и Django
Pycon Russia 2013 - Разработка через тестирование в Python и DjangoIlya Shalyapin
 
Олексій Стульніков “WinAppDriver – автоматизація Desktop ніколи не була такою...
Олексій Стульніков “WinAppDriver – автоматизація Desktop ніколи не була такою...Олексій Стульніков “WinAppDriver – автоматизація Desktop ніколи не була такою...
Олексій Стульніков “WinAppDriver – автоматизація Desktop ніколи не була такою...Dakiry
 
SWD Page Recorder: Записывает PageObject'ы со скоростью ниндзя SeleniumCamp 2014
SWD Page Recorder: Записывает PageObject'ы со скоростью ниндзя SeleniumCamp 2014SWD Page Recorder: Записывает PageObject'ы со скоростью ниндзя SeleniumCamp 2014
SWD Page Recorder: Записывает PageObject'ы со скоростью ниндзя SeleniumCamp 2014Dmytro Zharii
 
Что могут статические анализаторы, чего не могут программисты и тестировщики
Что могут статические анализаторы, чего не могут программисты и тестировщикиЧто могут статические анализаторы, чего не могут программисты и тестировщики
Что могут статические анализаторы, чего не могут программисты и тестировщикиAndrey Karpov
 
Где кончается react native? / Павел Кондратенко (Rambler&Co)
Где кончается react native? / Павел Кондратенко (Rambler&Co)Где кончается react native? / Павел Кондратенко (Rambler&Co)
Где кончается react native? / Павел Кондратенко (Rambler&Co)Ontico
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишковcorehard_by
 
Автоматизация функционального тестирования REST API
Автоматизация функционального тестирования REST APIАвтоматизация функционального тестирования REST API
Автоматизация функционального тестирования REST APIPavel Asanov
 
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)Ontico
 
Читабельные отчеты для автоматизации на C# / Gallio / BDDfy
Читабельные отчеты для автоматизации на C# / Gallio / BDDfyЧитабельные отчеты для автоматизации на C# / Gallio / BDDfy
Читабельные отчеты для автоматизации на C# / Gallio / BDDfyDmytro Zharii
 
Умный компилятор в Java 9: насколько он умён? Сергей Петунин, Центр ИТ
 Умный компилятор в Java 9: насколько он умён? Сергей Петунин, Центр ИТ  Умный компилятор в Java 9: насколько он умён? Сергей Петунин, Центр ИТ
Умный компилятор в Java 9: насколько он умён? Сергей Петунин, Центр ИТ it-people
 

What's hot (20)

Alexander manuhin selenium_php_v2.0
Alexander manuhin selenium_php_v2.0Alexander manuhin selenium_php_v2.0
Alexander manuhin selenium_php_v2.0
 
Тестируй это / Виктор Русакович (GP Solutions)
Тестируй это / Виктор Русакович (GP Solutions)Тестируй это / Виктор Русакович (GP Solutions)
Тестируй это / Виктор Русакович (GP Solutions)
 
Самодельная параметризация и параллелизация тестов на Webdriver (JS)
Самодельная параметризация и параллелизация тестов на Webdriver (JS) Самодельная параметризация и параллелизация тестов на Webdriver (JS)
Самодельная параметризация и параллелизация тестов на Webdriver (JS)
 
Особенности разработки API / Всеволод Шмыров (Яндекс)
Особенности разработки API / Всеволод Шмыров (Яндекс)Особенности разработки API / Всеволод Шмыров (Яндекс)
Особенности разработки API / Всеволод Шмыров (Яндекс)
 
Превышаем скоросные лимиты с Angular 2
Превышаем скоросные лимиты с Angular 2Превышаем скоросные лимиты с Angular 2
Превышаем скоросные лимиты с Angular 2
 
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшeQA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
 
Behat в PHP с использованием Behat и Mink
Behat в PHP с использованием Behat и MinkBehat в PHP с использованием Behat и Mink
Behat в PHP с использованием Behat и Mink
 
Превышаем скоростные лимиты с Angular 2
Превышаем скоростные лимиты с Angular 2Превышаем скоростные лимиты с Angular 2
Превышаем скоростные лимиты с Angular 2
 
Drupal Camp Kyiv 2013. Удобная разработка drupal проекта. Полезные модули.
Drupal Camp Kyiv 2013. Удобная разработка drupal проекта. Полезные модули.Drupal Camp Kyiv 2013. Удобная разработка drupal проекта. Полезные модули.
Drupal Camp Kyiv 2013. Удобная разработка drupal проекта. Полезные модули.
 
FPUG Dzyga presentation
FPUG Dzyga presentationFPUG Dzyga presentation
FPUG Dzyga presentation
 
Pycon Russia 2013 - Разработка через тестирование в Python и Django
Pycon Russia 2013 - Разработка через тестирование в Python и DjangoPycon Russia 2013 - Разработка через тестирование в Python и Django
Pycon Russia 2013 - Разработка через тестирование в Python и Django
 
Олексій Стульніков “WinAppDriver – автоматизація Desktop ніколи не була такою...
Олексій Стульніков “WinAppDriver – автоматизація Desktop ніколи не була такою...Олексій Стульніков “WinAppDriver – автоматизація Desktop ніколи не була такою...
Олексій Стульніков “WinAppDriver – автоматизація Desktop ніколи не була такою...
 
SWD Page Recorder: Записывает PageObject'ы со скоростью ниндзя SeleniumCamp 2014
SWD Page Recorder: Записывает PageObject'ы со скоростью ниндзя SeleniumCamp 2014SWD Page Recorder: Записывает PageObject'ы со скоростью ниндзя SeleniumCamp 2014
SWD Page Recorder: Записывает PageObject'ы со скоростью ниндзя SeleniumCamp 2014
 
Что могут статические анализаторы, чего не могут программисты и тестировщики
Что могут статические анализаторы, чего не могут программисты и тестировщикиЧто могут статические анализаторы, чего не могут программисты и тестировщики
Что могут статические анализаторы, чего не могут программисты и тестировщики
 
Где кончается react native? / Павел Кондратенко (Rambler&Co)
Где кончается react native? / Павел Кондратенко (Rambler&Co)Где кончается react native? / Павел Кондратенко (Rambler&Co)
Где кончается react native? / Павел Кондратенко (Rambler&Co)
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
 
Автоматизация функционального тестирования REST API
Автоматизация функционального тестирования REST APIАвтоматизация функционального тестирования REST API
Автоматизация функционального тестирования REST API
 
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
Как мы разрабатываем новый фронтенд / Филипп Нехаев (Tinkoff.ru)
 
Читабельные отчеты для автоматизации на C# / Gallio / BDDfy
Читабельные отчеты для автоматизации на C# / Gallio / BDDfyЧитабельные отчеты для автоматизации на C# / Gallio / BDDfy
Читабельные отчеты для автоматизации на C# / Gallio / BDDfy
 
Умный компилятор в Java 9: насколько он умён? Сергей Петунин, Центр ИТ
 Умный компилятор в Java 9: насколько он умён? Сергей Петунин, Центр ИТ  Умный компилятор в Java 9: насколько он умён? Сергей Петунин, Центр ИТ
Умный компилятор в Java 9: насколько он умён? Сергей Петунин, Центр ИТ
 

Viewers also liked

Building next gen android library with gradle
Building next gen android library with gradleBuilding next gen android library with gradle
Building next gen android library with gradleAnton Rutkevich
 
Gradle. Новый уровень автоматизации для Android
Gradle. Новый уровень автоматизации для AndroidGradle. Новый уровень автоматизации для Android
Gradle. Новый уровень автоматизации для AndroidAnton Rutkevich
 
Modern Android UI, or not by Action Bar alone
Modern Android UI, or not by Action Bar aloneModern Android UI, or not by Action Bar alone
Modern Android UI, or not by Action Bar aloneAnton Rutkevich
 
Cutting edge android stack. One year later
Cutting edge android stack. One year laterCutting edge android stack. One year later
Cutting edge android stack. One year laterAnton Rutkevich
 
Study: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving CarsStudy: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving CarsLinkedIn
 
Hype vs. Reality: The AI Explainer
Hype vs. Reality: The AI ExplainerHype vs. Reality: The AI Explainer
Hype vs. Reality: The AI ExplainerLuminary Labs
 

Viewers also liked (6)

Building next gen android library with gradle
Building next gen android library with gradleBuilding next gen android library with gradle
Building next gen android library with gradle
 
Gradle. Новый уровень автоматизации для Android
Gradle. Новый уровень автоматизации для AndroidGradle. Новый уровень автоматизации для Android
Gradle. Новый уровень автоматизации для Android
 
Modern Android UI, or not by Action Bar alone
Modern Android UI, or not by Action Bar aloneModern Android UI, or not by Action Bar alone
Modern Android UI, or not by Action Bar alone
 
Cutting edge android stack. One year later
Cutting edge android stack. One year laterCutting edge android stack. One year later
Cutting edge android stack. One year later
 
Study: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving CarsStudy: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving Cars
 
Hype vs. Reality: The AI Explainer
Hype vs. Reality: The AI ExplainerHype vs. Reality: The AI Explainer
Hype vs. Reality: The AI Explainer
 

Similar to Plugin for plugin, or extending android new build system

Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Ontico
 
iOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationiOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationAndrii Dzynia
 
Domain Specific Languages (for business rules)
Domain Specific Languages (for business rules)Domain Specific Languages (for business rules)
Domain Specific Languages (for business rules)Anton Arhipov
 
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...CodeFest
 
Mobile automation uamobile
Mobile automation uamobileMobile automation uamobile
Mobile automation uamobileUA Mobile
 
Node.js введение в технологию, КПИ #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPINode.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ #ITmeetingKPITimur Shemsedinov
 
IT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчикаIT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчикаMikhail Chinkov
 
REPL в Node.js: улучшаем быт разработчик
REPL в Node.js: улучшаем быт разработчикREPL в Node.js: улучшаем быт разработчик
REPL в Node.js: улучшаем быт разработчикIT61
 
Евгений Жарков "Как быть хорошим фронтенд-разработчиком"
Евгений Жарков "Как быть хорошим фронтенд-разработчиком"Евгений Жарков "Как быть хорошим фронтенд-разработчиком"
Евгений Жарков "Как быть хорошим фронтенд-разработчиком"Fwdays
 
JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"oelifantiev
 
Easy authcache 2 кеширование для pro родионов игорь
Easy authcache 2   кеширование для pro родионов игорьEasy authcache 2   кеширование для pro родионов игорь
Easy authcache 2 кеширование для pro родионов игорьdrupalconf
 
"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone
"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone
"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evroneit-people
 
Фундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел ТайкалоФундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел ТайкалоStanfy
 
Опыт разработки эффективного SPA
Опыт разработки эффективного SPAОпыт разработки эффективного SPA
Опыт разработки эффективного SPAEugene Abrosimov
 
Scala, SBT & Play! for Rapid Application Development
Scala, SBT & Play! for Rapid Application DevelopmentScala, SBT & Play! for Rapid Application Development
Scala, SBT & Play! for Rapid Application DevelopmentAnton Kirillov
 
Распределённое нагрузочное тестирование на Java
Распределённое нагрузочное тестирование на JavaРаспределённое нагрузочное тестирование на Java
Распределённое нагрузочное тестирование на Javaaragozin
 
Easy authcache 2 кэширование для pro. Родионов Игорь
Easy authcache 2   кэширование для pro. Родионов ИгорьEasy authcache 2   кэширование для pro. Родионов Игорь
Easy authcache 2 кэширование для pro. Родионов ИгорьPVasili
 

Similar to Plugin for plugin, or extending android new build system (20)

Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
Vue.js и его брат-близнец Vue-server.js / Андрей Солодовников (НГС)
 
iOS and Android Mobile Test Automation
iOS and Android Mobile Test AutomationiOS and Android Mobile Test Automation
iOS and Android Mobile Test Automation
 
Domain Specific Languages (for business rules)
Domain Specific Languages (for business rules)Domain Specific Languages (for business rules)
Domain Specific Languages (for business rules)
 
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
 
Mobile automation uamobile
Mobile automation uamobileMobile automation uamobile
Mobile automation uamobile
 
Java 9 - Back to the Future
Java 9 - Back to the FutureJava 9 - Back to the Future
Java 9 - Back to the Future
 
Node.js введение в технологию, КПИ #ITmeetingKPI
Node.js введение в технологию, КПИ  #ITmeetingKPINode.js введение в технологию, КПИ  #ITmeetingKPI
Node.js введение в технологию, КПИ #ITmeetingKPI
 
IT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчикаIT-инфраструктура. FAQ для разработчика
IT-инфраструктура. FAQ для разработчика
 
REPL в Node.js: улучшаем быт разработчик
REPL в Node.js: улучшаем быт разработчикREPL в Node.js: улучшаем быт разработчик
REPL в Node.js: улучшаем быт разработчик
 
CD with Jenkins. Lessons Learned
CD with Jenkins. Lessons LearnedCD with Jenkins. Lessons Learned
CD with Jenkins. Lessons Learned
 
Java 9 - кратко о новом
Java 9 -  кратко о новомJava 9 -  кратко о новом
Java 9 - кратко о новом
 
Евгений Жарков "Как быть хорошим фронтенд-разработчиком"
Евгений Жарков "Как быть хорошим фронтенд-разработчиком"Евгений Жарков "Как быть хорошим фронтенд-разработчиком"
Евгений Жарков "Как быть хорошим фронтенд-разработчиком"
 
JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"JavaScript-модули "из прошлого в будущее"
JavaScript-модули "из прошлого в будущее"
 
Easy authcache 2 кеширование для pro родионов игорь
Easy authcache 2   кеширование для pro родионов игорьEasy authcache 2   кеширование для pro родионов игорь
Easy authcache 2 кеширование для pro родионов игорь
 
"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone
"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone
"VUE.JS как реакт с человеческим лицом" Дулецкий Вольдэмар, Evrone
 
Фундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел ТайкалоФундаментальные основы разработки под iOS. Павел Тайкало
Фундаментальные основы разработки под iOS. Павел Тайкало
 
Опыт разработки эффективного SPA
Опыт разработки эффективного SPAОпыт разработки эффективного SPA
Опыт разработки эффективного SPA
 
Scala, SBT & Play! for Rapid Application Development
Scala, SBT & Play! for Rapid Application DevelopmentScala, SBT & Play! for Rapid Application Development
Scala, SBT & Play! for Rapid Application Development
 
Распределённое нагрузочное тестирование на Java
Распределённое нагрузочное тестирование на JavaРаспределённое нагрузочное тестирование на Java
Распределённое нагрузочное тестирование на Java
 
Easy authcache 2 кэширование для pro. Родионов Игорь
Easy authcache 2   кэширование для pro. Родионов ИгорьEasy authcache 2   кэширование для pro. Родионов Игорь
Easy authcache 2 кэширование для pro. Родионов Игорь
 

Plugin for plugin, or extending android new build system

  • 1.
  • 2. Plugin for plugin, or extending Android New Build System Anton Rutkevich
  • 3. About me › 4+ years of Android development › Mobile game-dev experience › At Yandex: 1. Mobile Yandex.Metrica 2. Continuous Integration
  • 4. Не удается отобразить рисунок. Возможно, рисунок поврежден или недостаточно памяти для его открытия. Перезагрузите компьютер, а затем снова откройте файл. Если вместо рисунка все еще отображается красный крестик, попробуйте удалить рисунок и вставить его заново. Why do I need this? Intro
  • 5. What can be done? › Additional resources/code/manifest processing › Output processing (apk, aar, jar) › Other things
  • 6. Story Prod / test servers Flavors! LoTgesst o /n /poroffd AaUndnasil qyotunice/s bo uffi ld numb...e r! I want to configure it myself! 2 Flav3o rs! FlaHvmorms?.. . Manager Android dev
  • 7. How should it work Java code build.gradle Teamcity Actual value: "https://my.server.com" CI server can do it Our job
  • 8. Insert CI value into BuildConfig.java // app/build.gradle apply plugin: 'com.android.application' android {" defaultConfig { buildConfigField "String", "URL", ""${teamcity['server-url']}"" buildConfigField "String", "URL", ""#server-url"" }" } project.teamcity = [ "server-url" : "https://my.server.com" // ..." ] url']}"".
  • 9. Use BuildConfig.java from Java public class SomeJavaClass { " // ... public static final String SERVER_URL = "https://my.server.com"; public static final String SERVER_URL = BuildConfig.URL; // ... }
  • 10. BuildConfig placeholder plugin › Replaces placeholder values with values from some map › Map can come from anywhere
  • 11. Goal // app/build.gradle apply plugin: 'com.android.application' apply plugin: 'placeholder' " placeholder {" replacements = project.teamcity } android {" defaultConfig {" buildConfigField "String", "URL", ""#server-url""" }" }
  • 12. Table of contents › Gradle basics › New Build System workflow › Hello, Gradle plugin! › Extending Android New Build System
  • 13. Не удается отобразить рисунок. Возможно, рисунок поврежден или недостаточно памяти для его открытия. Перезагрузите компьютер, а затем снова откройте файл. Если вместо рисунка все еще отображается красный крестик, попробуйте удалить рисунок и вставить его заново. Tools we will use Gradle basics
  • 15. Tasks › Can be configured with { } › Consist of actions › Can depend on other tasks › Can have inputs / outputs
  • 16. Task consists of actions Task Action Action Action Action doFirst() doLast(), or <<
  • 17. Tasks execution order Task 2 Task 3 Task 4 dependsOn dependsOn dependsOn Execution order Task 1 Task 2 Task 3 Task 4 Task 1
  • 18. Outputs Task inputs / outputs Inputs Task Inputs & outputs did not change => UP-TO-DATE
  • 19. Task example task myTask { ext.myMessage = "hello" } myTask << { println myMessage } task otherTask(dependsOn: myTask)
  • 20. Task example output >> gradle otherTask :app:myTask hello :app:otherTask
  • 21. Build lifecycle settings.gradle build.gradle Initialization Configuration Execution Projects creation Projects configuration Tasks creation Tasks configuration project.afterEvaluate { } Task graph execution Task graph Build initialization
  • 22. The New Build System workflow Не удается отобразить рисунок. Возможно, рисунок поврежден или недостаточно памяти для его открытия. Перезагрузите компьютер, а затем снова откройте файл. Если вместо рисунка все еще отображается красный крестик, попробуйте удалить рисунок и вставить его заново. What's so special?
  • 23. What tasks will be launched? build check assemble assembleDebug assembleRelease Guaranteed assemble<VariantName>
  • 25. Tasks we will need assemble<VariantName> .... generate<VariantName>BuildConfig .... compile<VariantName>Java ....
  • 26. Variant API Source code is your documentation! › Access to most variant's tasks › Variant output related properties › Different for apps & libraries
  • 27. Hello, Gradle plugin! Не удается отобразить рисунок. Возможно, рисунок поврежден или недостаточно памяти для его открытия. Перезагрузите компьютер, а затем снова откройте файл. Если вместо рисунка все еще отображается красный крестик, попробуйте удалить рисунок и вставить его заново. The first steps
  • 28. The very basic one src/main/groovy/com/example/gradle/PlaceholderPlugin.gradle public class PlaceholderPlugin implements Plugin<Project> { @Override" void apply(Project project) { project.task('hello') << {" println "Hello Gradle plugin!" } } }
  • 29. Bind plugin class to plugin name src/main/resources/META-INF/gradle-plugins/placeholder.properties implementation-class=com.example.gradle.PlaceholderPlugin
  • 31. Add extension src/main/groovy/com/example/gradle/PlaceholderExtension.gradle class PlaceholderExtension {" def replacements = [:] }"
  • 32. Add extension @Override" void apply(Project project) {" PlaceholderExtension extension = project.extensions.create(" "placeholder", PlaceholderExtension" ); project.task('hello') << { println "Hello Gradle plugin!" println "Hi, ${project.placeholder.replacements}" } }"
  • 33. Use extension // app/build.gradle apply plugin: 'placeholder'" " placeholder {" replacements = ["server-url" : "https://my.server.com"] }" --------------------------------------------- >> gradle hello :app:hello" Hi, [server-url:https://my.server.com]
  • 34. Extending The New Build System Не удается отобразить рисунок. Возможно, рисунок поврежден или недостаточно памяти для его открытия. Перезагрузите компьютер, а затем снова откройте файл. Если вместо рисунка все еще отображается красный крестик, попробуйте удалить рисунок и вставить его заново. Let's do it!
  • 35. Check for New Build System // PlaceholderPlugin.groovy @Override" void apply(Project project) { if (project.hasProperty("android")) { PlaceholderExtension extension = project.extensions.create(" "placeholder", PlaceholderExtension" ); def android = project.android // all code goes here } }"
  • 36. Let the New Build System do its job // PlaceholderPlugin.apply() if (project.hasProperty("android")) { PlaceholderExtension extension = project.extensions.create(" "placeholder", PlaceholderExtension" ); def android = project.android project.afterEvaluate {" // at this point we have all // tasks from New Build System } }
  • 37. Process every variant // PlaceholderPlugin.apply() project.afterEvaluate { if (android.hasProperty('applicationVariants')) { android.applicationVariants.all { variant -> addActions(project, variant, extension) } } else if (android.hasProperty('libraryVariants')) { android.libraryVariants.all { variant -> addActions(project, variant, extension) } } }
  • 38. Add task // PlaceholderPlugin.groovy def addActions(Project project, variant, PlaceholderExtension extension) { Task processPlaceholders = project.task( "process${variant.name.capitalize()}Placeholders" ) processPlaceholders << { println "I will replace ${variant.name}!" } }
  • 39. Insert task into build process assemble<VariantName> .... generate<VariantName>BuildConfig .... process<VariantName>Placeholders compile<VariantName>Java ....
  • 40. Insert task into build process // PlaceholderPlugin.groovy def addActions(Project project, variant, PlaceholderExtension extension) { Task processPlaceholders = ... ... variant.javaCompile.dependsOn processPlaceholders" processPlaceholders.dependsOn variant.generateBuildConfig }
  • 41. Does it really work? >> gradle assembleDebug :app:preBuild ... :app:generateDebugBuildConfig ... :app:processDebugPlaceholders I will replace debug! :app:compileDebugJava ...
  • 42. Actual work. Perform replacements // PlaceholderPlugin.addActions() processPlaceholders << { def buildConfigFile = getBuildConfig(variant) " extension.replacements.each { replacement ->" project.ant.replace(" file: buildConfigFile," token: "#${replacement.key}", value: replacement.value" )" } }
  • 43. Handling inputs / outputs process Placeholders BuildConfig.java BuildConfig.java BuildConfig.java replacements generate BuildConfig ... replacements << Action
  • 44. Replace task with 'doLast' // PlaceholderPlugin.addActions() processPlaceholders << { variant.generateBuildConfig << { def buildConfigFile = ... extension.replacements.each { ... } } variant.generateBuildConfig.inputs.property( "replacements", extension.replacements )
  • 46. Remember how to use it? // app/build.gradle apply plugin: 'com.android.application'" apply plugin: 'placeholder'" " placeholder {" replacements = project.teamcity }" " android {" defaultConfig {" buildConfigField "String", "URL", ""#server-url""" }" }
  • 47. Does it work? app/build/generated/source/buildConfig/debug/com/example/ sample/BuildConfig.java public final class BuildConfig {" // Fields from default config." public static final String URL = "https://my.server.com"; }
  • 48. Не удается отобразить рисунок. Возможно, рисунок поврежден или недостаточно памяти для его открытия. Перезагрузите компьютер, а затем снова откройте файл. Если вместо рисунка все еще отображается красный крестик, попробуйте удалить рисунок и вставить его заново. To summarize
  • 49. Key steps › Create Gradle plugin › Inside afterEvaluate { } › Process every variant › Add action to generateBuildConfig › Handle inputs / outputs
  • 50. What's next? › Default values support › Errors handling › Publish ( jcenter / mavenCentral / other )
  • 51. Links Gradle http://www.gradle.org/ The New Build System http://tools.android.com/tech-docs/new-build-system http://tools.android.com/tech-docs/new-build-system/build-workflow Github sample https://github.com/roottony/android-placeholder-plugin
  • 52. Thank you for your attention! Anton Rutkevich Senior software engineer antonrut@yandex-team.ru anton.rutkevich@gmail.com