Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Create an Android plugin using Kotlin
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Bruno Oliveira
September 24, 2016
Programming
75
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Create an Android plugin using Kotlin
Presentation @Google Developers Group Lisbon
27/09/2016
Bruno Oliveira
September 24, 2016
More Decks by Bruno Oliveira
See All by Bruno Oliveira
Speedy Development with Kotlin
bmoliveira
1
79
Other Decks in Programming
See All in Programming
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
1.2k
AIで開発が速くなった先で、開発チームは何を目指すか
shihochan
0
1.4k
APNsからLive Activityを開始する話
yumnumm
0
170
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
700
複雑なUIコンポーネントとの ⻑い付き合い⽅:波及するバグからテスト戦略を経て、安全な再設計へ
mixplace
0
420
Agents on Rails - Rails at Scale 2026
irinanazarova
0
560
Atomic Design, Enforced: Scaling Mobile Design Systems (next.app devCon / droidCon Berlin 2026)
steliosf
PRO
0
170
FactoryBotをやめればRSpecは速くなるのか?
yuta_onishi_97
0
540
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
310
[ハンズオン]AIへの指示だけで「五目並べ」を作ってみよう
satoshi256kbyte
1
380
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
28
32k
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
750
Featured
See All Featured
Automating Front-end Workflow
addyosmani
1369
210k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
Optimizing for Happiness
mojombo
378
71k
Into the Great Unknown - MozCon
thekraken
41
2.8k
Bash Introduction
62gerente
615
220k
4 Signs Your Business is Dying
shpigford
187
23k
A designer walks into a library…
pauljervisheath
211
25k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
930
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
480
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
The Cult of Friendly URLs
andyhume
79
7k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Transcript
Create your Gradle plugin using Kotlin Bruno Oliveira Mobile developer
@Faber-Ventures
Build a Gradle plugin using Kotlin • Why Kotlin •
Localizable.io • Android specific plugin • Build the plugin step-by-step
Localizable.io • Managing strings in a live app is a
problem
Localizable.io • Making the developer life easier
Localizable.io • Change directly in Produc3on
Our vision • Localizable.setup(this) • Localizable.getString(R.string.welcome) • Localizable.availableLocales() • Localizable.setLocale(Localizable.availableLocales().get(0))
Our vision
Why do we need a plugin? • Build (me analyse
android resources • Parse generated values folders • Extract Strings • Manifest • Make a seamless experience
What/How are we doing with it? • Extract strings from
values • Cache and send to server • Try to automate as much as possible
Biggest problems at start • Android studio • Trying to
implement the sample right in the same project • Deploy development dependency to local maven repo
Let's start
Let's start
Let's start
Setup dependencies aka build.gradle • Kotlin • GradleApi • Build
Tools apply plugin: "kotlin" dependencies { compile gradleApi() compile "org.jetbrains.kotlin:kotlin-stdlib:1.0.3" compile "com.android.tools.build:gradle:2.1.3" }
Declare a plugin • src/main/resources/META-INF.gradle-plugins
Declare a plugin • Plugin class class LocalizablePlugin : Plugin<Project>
{ override fun apply(project: Project?) { project?.let { ProjectHandler(it).createTasks() } } }
Declare a plugin • Use the plugin apply plugin: 'localizable'
buildscript { dependencies { classpath "io.localizable:sync:1.0.4-SNAPSHOT" } }
When tasks added fun createTasks() { if (!isAndroidProject) { throw
Throwable("You should apply android to your project first") } tasks.whenTaskAdded { handleTask(it) } }
Android build tools check private val isAndroidProject: Boolean by lazy
{ project.plugins.hasPlugin(AppPlugin::class.java) } private val appExtension: AppExtension by lazy { project.extensions.getByType(AppExtension::class.java) } private val flavorNames: List<String> by lazy { val configs = appExtension.productFlavors.map { it.name } if (configs.isNotEmpty()) configs else listOf("") } private val buildTypes: Collection<BuildType> by lazy { appExtension.buildTypes }
Handle everything • We don't wanna miss a thing. private
fun handleTask(task: Task) { buildTypes.forEach { build -> flavorNames.forEach { flavor -> processBuild(build.name, flavor, task) } } }
Find the One private fun processBuild(buildName: String, flavorName: String, task:
Task) { val taskAffix = LocalizableHelper.taskAffix(buildName, flavorName) val processTask = "process${taskAffix}Resources" if (processTask.equals(task.name)) { createLocalizableFromTask(task, taskAffix, buildName, flavorName) } }
Create a task val localizableTaskName = "localizable$taskAffix" val nTask =
project.task(localizableTaskName)
Execute • Execute block • Follow the behaviors • Use
the build cache folders if needed nTask.doFirst { val manifest = LocalizableHelper.manifestFileForTarget(project, buildName, flavorName) if (manifest == null) { println("Could not find any manifest file") return@doFirst } nTask.didWork = LocalizableTask(project, manifest, localizableTaskName).syncResources() }
Add task to Android stack • Task in the middle
• mergeDebugEpicResources > localizableEpicResources > ProcessDebugEpicResources task.dependsOn(nTask) val mergeTask = "merge${taskAffix}Resources" project.tasks.getByName(localizableTaskName).dependsOn(mergeTask)
Execute order • mergeEpicDebugResources • localizableEpicDebugResources • processEpicDebugResources
Deploy locally Run the task - Command line ./gradlew :plugin:uploadArchives
uploadArchives { repositories { mavenDeployer { repository(url: mavenLocal().url) pom.groupId = GROUP_ID pom.artifactId = ARTIFACT_PLUGIN_ID pom.version = PLUGIN_VERSION } } }
Deploy locally Run the task - On interface
Debug :( • Network interceptor private val interceptor: HttpLoggingInterceptor by
lazy { val interceptor = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger { println(" -> $it") }) interceptor.level = HttpLoggingInterceptor.Level.BODY interceptor }
Deploy to Maven • guide to maven • h/p:/ /zserge.com/blog/gradle-maven-publish.html
• jitpack • jitpack.io
Contacts •
[email protected]
• github.com/bmoliveira • twi5er.com/_bmoliveira Localizable.io