Level up your Android build
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 46 | |
Author | ||
License | CC Attribution 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor. | |
Identifiers | 10.5446/47193 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | ||
Genre | ||
Abstract |
|
droidcon Berlin 20157 / 46
5
7
10
13
16
18
20
21
23
26
31
34
35
36
41
42
45
00:00
BitMobile appPhysical systemSet (mathematics)GoogolScripting languageoutputLecture/Conference
00:51
Mobile appScaling (geometry)Host Identity ProtocolRow (database)Theory of everythingLecture/Conference
01:29
Computing platformAndroid (robot)Projective planeBitRight angleLecture/Conference
02:02
Level (video gaming)Android (robot)BuildingComputer fileGradientWrapper (data mining)Plug-in (computing)Computer fileSet (mathematics)Domain namePhysical systemScripting languageProjective planeWrapper (data mining)CodeRootMobile appBitBuildingEnterprise architectureAndroid (robot)Right angleScaling (geometry)XML
03:24
Level (video gaming)Computer fileBuildingGradientWrapper (data mining)Category of beingComputer fileBitCodeRevision controlWrapper (data mining)Lecture/ConferenceComputer animation
04:08
Level (video gaming)Task (computing)Wrapper (data mining)UsabilityAssembly languageConnected spaceScripting languageBitWrapper (data mining)Task (computing)Keyboard shortcutSoftware testingAndroid (robot)Directory serviceGroup actionElectronic mailing listInstance (computer science)Right angleCASE <Informatik>
05:11
Right angleKeyboard shortcutAssembly languageBitScripting languageTask (computing)Default (computer science)Personal area networkWordPlug-in (computing)Mobile appBuildingAndroid (robot)WritingMeeting/InterviewLecture/Conference
06:19
Scripting languagePlug-in (computing)Android (robot)Social classRootLevel (video gaming)BuildingGoogolCompilerCore dumpBitCartesian coordinate systemUtility softwareComputer programmingProcess (computing)Multiplication signInstance (computer science)Task (computing)Run time (program lifecycle phase)Scripting languageLibrary (computing)Module (mathematics)Overhead (computing)Projective planeConfiguration spaceAndroid (robot)CodeStandard deviationBuildingComputer animation
07:51
Android (robot)Revision controlConfiguration spaceBuildingPhysical systemCuboidModule (mathematics)Goodness of fitPlug-in (computing)Right angleProcess (computing)BitLecture/Conference
08:30
GoogolCompilerCore dumpLevel (video gaming)Android (robot)BuildingType theoryCodeElectronic signatureLibrary (computing)Computer programmingRight angleConfiguration spaceWordFood energySocial classRevision controlSoftware testingMobile appFormal verificationCodeCategory of beingModule (mathematics)Android (robot)Source codePlug-in (computing)Computer animation
10:29
Bit error rateLibrary (computing)Social classElectronic mailing listComputer programmingTask (computing)Function (mathematics)GoogolMetropolitan area networkDescriptive statisticsMultiplication signFile archiverWebsiteLecture/Conference
11:14
Level (video gaming)Task (computing)File archiverInstance (computer science)CASE <Informatik>RoutingLogical constantVariable (mathematics)BuildingCodeTask (computing)Revision controlCategory of beingType theoryProjective planeGoodness of fitRootComputer animation
12:06
ExplosionJava appletAndroid (robot)Online helpGradientFundamental theorem of algebraCore dumpAndroid (robot)Goodness of fitContent (media)Java appletCausalityStress (mechanics)Roundness (object)Office suite
12:40
BuildingLevel (video gaming)Android (robot)Scaling (geometry)Software testingContinuous integrationOffice suiteGoodness of fitLogicSoftware developerBitWeb 2.0Server (computing)Presentation of a groupRootComputing platformSoftware testingMobile appWeb applicationContinuous integrationCodeRule of inferenceProcess (computing)Analytic continuation
13:46
Level (video gaming)Core dumpProjective planeJava appletModule (mathematics)Endliche ModelltheorieSoftware testingCodeWeb 2.0Mobile appLecture/ConferenceComputer animation
14:35
Level (video gaming)Core dumpAndroid (robot)BuildingGoogolWeb 2.0Projective planeServer (computing)Module (mathematics)Software testingEndliche ModelltheorieSampling (statistics)Java appletScripting languageGoogolComputer animationLecture/Conference
15:14
BuildingLevel (video gaming)Android (robot)DisintegrationJava appletFlow separationSoftware testingSet (mathematics)Source codeTask (computing)Social classFunction (mathematics)Coma BerenicesPoint (geometry)GoogolSoftware developerGoodness of fitCodeModule (mathematics)GodAndroid (robot)Software testingWeb 2.0Source codeProjective planeCore dumpINTEGRALLecture/ConferenceComputer animation
15:47
DisintegrationSoftware testingJava appletFlow separationSource codeSet (mathematics)Task (computing)Social classFunction (mathematics)Level (video gaming)Android (robot)BuildingRevision controlCore dumpSoftware testingCodeINTEGRALModule (mathematics)Unit testingTask (computing)Standard deviationRight angleSource codeFilm editingDatabaseMultiplication signLibrary (computing)Bit rateRevision controlTraffic reportingPlug-in (computing)Goodness of fitAutomationLecture/ConferenceComputer animation
17:03
Bit error rateLevel (video gaming)Task (computing)CodeRule of inferenceComputer fileInheritance (object-oriented programming)Rule of inferenceSoftware bugSource codeCuboidCodeConfiguration spaceAndroid (robot)Plug-in (computing)Multiplication signJava appletTraffic reportingTask (computing)Server (computing)Projective planeLecture/ConferenceComputer animation
18:17
Level (video gaming)Task (computing)CodeRule of inferenceAndroid (robot)BuildingComputer fileInheritance (object-oriented programming)Projective planeCategory of beingTraffic reportingTask (computing)CodeParameter (computer programming)CuboidProduct (business)Multiplication signGroup actionConfiguration spaceLecture/ConferenceComputer animation
19:25
Disk read-and-write headTraffic reportingServer (computing)Right angleCategory of beingLecture/Conference
19:56
BuildingLevel (video gaming)Android (robot)Physical systemContinuous integrationNumberVariable (mathematics)BuildingProcess (computing)Server (computing)Instance (computer science)Integrated development environmentRevision controlDrop (liquid)Level (video gaming)Computer animation
20:27
Bit error rateRepetitionLevel (video gaming)Android (robot)BuildingTask (computing)Software testingCharacteristic polynomialAndroid (robot)BuildingPhysical systemSoftware testingMultiplication signPower (physics)CASE <Informatik>Pointer (computer programming)Plug-in (computing)Tablet computerSocial classOperator (mathematics)Exception handlingMixture modelLevel (video gaming)Lecture/ConferenceComputer animation
21:39
Task (computing)Software testingAndroid (robot)Characteristic polynomialBuildingLevel (video gaming)Revision controlReading (process)Computer fileChainException handlingSocial classVariable (mathematics)Right angleConnected spaceOperator (mathematics)Data storage deviceMessage passingTask (computing)Projective planeSource codeMathematicsRevision controlScripting languagePhysical systemSoftware testingElectronic mailing listPerformance appraisalBitAndroid (robot)Numbering schemeRepository (publishing)Phase transitionHecke operatorResultantFlow separationBuildingLogicNumberMultiplication signPlug-in (computing)Computer animation
25:31
Bit error rateAndroid (robot)BuildingLevel (video gaming)RootScripting languageDisk read-and-write headRevision controlCodeSource codeJava appletAndroid (robot)BuildingLibrary (computing)Social classMereologyString (computer science)Repository (publishing)MathematicsVariable (mathematics)Message passingRevision controlWrapper (data mining)Lecture/ConferenceComputer animation
26:37
FehlerbaumLevel (video gaming)GoogolComputer-generated imageryComputer fileEmailPlug-in (computing)Revision controlWebsiteGoodness of fitGoogolTask (computing)Electronic mailing listOffice suiteFunctional (mathematics)MetadataLecture/ConferenceComputer animation
27:58
Level (video gaming)Task (computing)Android (robot)Data typeBitProduct (business)CASE <Informatik>Android (robot)MetadataHookingType theoryOperator (mathematics)Plug-in (computing)Computing platformLoop (music)Lecture/ConferenceComputer animation
28:57
Task (computing)Android (robot)Data typeLevel (video gaming)Configuration spaceRootScripting languageComplex (psychology)BuildingComputer fileGoogolCompilerCodeTask (computing)WeightLogicMultiplication signGoodness of fitHookingComputer programmingElectronic mailing listData storage deviceCartesian coordinate systemBitLecture/ConferenceComputer animation
30:04
Level (video gaming)Configuration spaceRootScripting languageComplex (psychology)BuildingComputer fileGoogolCompilerRule of inferenceInstance (computer science)ProgrammierstilUniform resource locatorGoodness of fitRevision controlProjective planeRootMessage passingComputer animation
30:53
RepetitionConfiguration spaceRootScripting languageBuildingComplex (psychology)Shared memoryGoogolCompilerComputer fileLevel (video gaming)Task (computing)Library (computing)Social classAndroid (robot)Software testingGroup actionExecution unitStatement (computer science)Limit (category theory)Function (mathematics)Utility softwareRight angleCASE <Informatik>Computer programmingSoftware frameworkoutputCompilation albumBuildingTask (computing)Functional (mathematics)Mobile appRevision controlLecture/ConferenceXMLComputer animation
32:17
SynchronizationComputer-generated imageryComputer fileTask (computing)Scripting languageBackupLevel (video gaming)Human migrationDemo (music)DatabaseData modelAndroid (robot)Plug-in (computing)Software testingComputer fileCuboidVirtual machineRight angleSpeech synthesisSoftware developerAlgebraic closureDatabaseMoving average1 (number)Configuration spaceScripting languageMedical imagingTask (computing)Projective planeLecture/ConferenceComputer animation
33:40
Human migrationDemo (music)DatabaseData modelLevel (video gaming)CodeTemplate (C++)Table (information)Fluid staticsString (computer science)DatabaseInformationJava appletLatent heatType theoryCodeTemplate (C++)Endliche ModelltheorieCASE <Informatik>Table (information)Plug-in (computing)MereologyObject-relational mappingDefault (computer science)Theory of relativityObject (grammar)BuildingAndroid (robot)Lecture/ConferenceComputer animation
35:11
Hydraulic jumpCodeBootingPhysical systemBitCompilerDatabaseMultiplication signMathematical analysisPlug-in (computing)Android (robot)Task (computing)Building
36:01
Level (video gaming)Scripting languageAndroid (robot)Repository (publishing)Plug-in (computing)Scripting languageCartesian coordinate systemSocial classAndroid (robot)Mobile appPlug-in (computing)Java appletMeta elementFluid staticsMultiplication signProgramming paradigmExterior algebraAlgebraic closureLecture/ConferenceComputer animation
37:03
Hill differential equationAndroid (robot)BuildingLevel (video gaming)Software testingOrder (biology)Reading (process)Plug-in (computing)Software testingWordLecture/ConferenceComputer animation
37:37
Lipschitz-StetigkeitSoftware developerLecture/Conference
Transcript: English(auto-generated)
00:05
This is Volker, and we're working at Novoda, and we would like to talk a bit about our experience that we made with the Android grill build system. It was announced at the Google I.O. 2013, and then finally the first release, 1.0,
00:24
was released in December last year. So not too old, but we tried to adopt as early as possible, we've played with it, and we would like to share our experience. So build scripting and such can be quite dry, so we try to take you on a journey as
00:44
a young entrepreneur and explain on the way. So let's assume one morning I have an idea for the next 100 million user app. Okay, wait a second here.
01:00
I think that thing wouldn't fly. Look at the people here in the first row, empty faces already. These two old guys having the next big thing idea, you know, this doesn't scale. So we have to do something about it. We have to hipster up, so I hope it's more convincing now.
01:21
We have an idea for 100 million user app. It's called Fugel Gotos, and we want to really build it. It's the next big thing, and so we choose a platform, let's say Android. Of course. Why not? Nearly 1 billion activations, and we want to target them all.
01:44
We know a bit of that stuff that helps as well, right? Yeah. So let's go. We installed Android Studio. We go through the new Android project wizard, and then we are ready to go. Let's do it. So let's look at the stuff we get created by the new project wizard, actually.
02:02
The first stop, if you look at the build stuff, is probably the build.gradle file located in the apps subfolder, and you're probably all familiar with that stuff by now. So why is it called build.gradle? The new Android build system is based on Gradle, which is great, because Gradle is actually
02:22
battle-tested in the enterprise world. It's been around for almost 10 years. It's stable, it scales, and it can handle really big builds, and now we also have it on Android. So it's great. Yeah, what happens here, so there's a special Gradle plugin now, the Android plugin. We apply it, and then we can configure and describe our build.
02:42
So this is really a declarative build system we have here. We really model our Android domain here, and this is how it looks like. The Android project is described just by the script. So, no executable code here, in that sense. Right, so we don't know what it does actually.
03:01
Hopefully it does the right thing. And then you have more? Yeah, there's actually a bit more. We have seen the first build.gradle file in the app folder, but there's another one in the root folder, there's the Gradle subfolder with the wrapper subfolder in that. And more properties. So the interesting thing is the settings Gradle, it says, here we have a multi-project
03:25
multi-module project, and it uses these two big Gradle files to go through the build stuff. So we have some properties. So we have a multi-project build here with just one sub-project, but that's mid-scale,
03:40
we can scale that up later on. And this Gradle wrapper, what does it do? We want reproducible builds, so Gradle comes with the concept of a wrapper. That means this wrapper makes sure that we always run with a fixed version of Gradle, and if it's not already there, it gets downloaded, and so we make sure that we always run on the
04:03
same version. So all is good. You can check out your code, you run your build, and you are where you left. So let's see what we get. No tasks, no actions, we've seen so far, so we ask Gradle, what do you have for us? Show me the stuff, right? This is what we get. So you can do tests, you can install, you can sign, so really long lists, and long names
04:30
also. So you have the possibility to shortcut them by using camera case, so only the first few bits. So this is nice already, yeah? So you can just write C capital A T instead of connected Android test for instance, right?
04:47
This is nice, shortens the stuff. You can have more than one task at the command line, so clean, assemble, could be run, this is nice. But this Gradle W stuff is a bit ugly, especially with the dot slash, you know, you have to
05:02
be aware of the directory where the wrapper lives, right? So it's a bit ugly. Can we do something about it? So make it shorter. We installed a small tool that's called GDAP, so for Gradle W, it's a small script that helps you to shortcut the task file, so you just write GW, wait, where is it?
05:24
Click again, yeah, I had that before, sorry, it was the next, I think, it doesn't work. Ah, here we have it. Yeah, GW, clean, assemble, and then you're good to go. Yeah, and it allows for nice shortcuts, you know, as well. So yeah, you can just write GW here, and it even works from subfolders, you mentioned
05:44
it, right? Yeah, and then, wait, you can't really run something? Yeah, this seems weird, right? So there's so much stuff here, but in Android Studio, I just click a button, and if I have a connected device, the app gets run on my device, so. I think we should use a Gradle plugin to do it.
06:02
Right, if it's not there by default, let's pull in some stuff that does it for us, and Gradle is extensible. So the first plugin, there's an Android command plugin, that does, doesn't work, yeah. So Android command plugin provided by community, and it helps you to do GW run a build.
06:25
Run debug down there, and what you see here, it's a build time, build script dependencies that we have to add, so there are actually two kinds, you know, the dependency we've seen earlier in your project, here it's a build script dependency, yeah, we pull it in, and then we apply it in our application module, build script, and all is good.
06:44
We have more tasks even, and we have the run task there, nice, okay, so, yeah, what's next? Okay, now let's start developing, let's, yeah, we have this great idea and we want
07:00
to make it now, right, so we want to build that stuff, so let's sit down and program, and of course we want to focus on the great idea we have, and not on all the stuff that's already solved, so there are a lot of great libraries out there, we just want to use them, and Gradle makes it easy to do so, we have the concept of a dependency configuration
07:21
in Gradle, and there are some predefined configurations like compile and test compile, and this is all well and nice for the standard libraries like Guava for instance, but probably many of you know that the Android annotation processing utilities are kind of on the rise,
07:41
because they don't add much runtime overhead, so they generate code for you, but these tools have, you know, are only needed at compile time, they are not needed at runtime, and this isn't really well supported by Android Studio, by the Gradle Android build out of the box. We need another plugin, yeah, so let's pull in another plugin, it's the Gradle Android,
08:03
what's it called, the Gradle APT plugin, APT plugin, so we apply it in the same way we applied the command plugin, and then you have a new configuration for the dependencies only for your annotation processing, right, and now you can use all the good stuff like dagger, butter knife, auto value, yeah, and there are more configurations produced
08:23
by the Android build systems if you use flavors, so we want to have a paid version and a free version, that's obvious, so we use, we define in our Android module that we have flavors, one free flavor and one paid flavor, and the Android plugin creates
08:40
a new dependency configuration, so the dependencies I use there, it's for the license verification checker, and it is only included in the paid version. Right, so we have this nice flavor concept, can build different versions, little diverging versions of our final app, this is nice, and what's behind, you have the dependencies
09:05
in the source set for the paid version, so if you write a class in the paid version source set, then you can use the license checker, and in the free version, you don't have it, and we try to kind of describe the best practice, how you handle these kind
09:23
of dependencies, but probably it's not really Gradle, so we can talk about that. Skip it, it's not Gradle, don't want it now. So we have developed this app now, we are done, it was a busy afternoon, and we really
09:42
want to ship it, but we shouldn't rush it out, we should actually run ProGuard before. Yeah, we want to target the Android One devices, there are low end devices out there, and we don't want to ship a bloated APK, so we want to make sure that only the stuff remains in there, that's really valuable, so it's easy to switch that stuff on, it's
10:03
just two properties up there, but with ProGuard, it has its quirks, so especially when you rely on third party libraries, you have to be careful that you update the ProGuard configuration to what the library needs, so do it early on and then test on your release
10:23
build so that you avoid bad surprises. In the community there are also code snippets, how to deal with this, so there's a library also to use annotations to say which classes you want to keep, so there's the, what's
10:42
the name? Squad Leader. Squad Leader, and the list of snippets, so now we have a small APK, and we want to upload it Google Play, so we go to the website with all manually, and it's a lot of work to do, lots of description stuff, screenshots, video, what else do we need?
11:02
You have to do it, that's the way. And then of course we want to archive what we have just released, so not only the APK, but also maybe the ProGuard outputs, and it's time for first custom task, now Gradle has a concept of tasks, and we can just define, okay we want to copy things, so we create
11:22
a task of type copy, we call it archive release in this case, and then we can just configure it nicely, so that it archives the produced artifacts that we've just created. It's really just configuring an existing task type. And maybe what's interesting to note here is that we can make use of Gradle's extra
11:41
properties, it's kind of big constants or variables, how you put it, and then you can reference them inside your big logic, like we do here for instance, with the version name and version code and the other things. This is nice because it's also visible in sub-projects, so you can define some of that
12:00
stuff in your root project, and then it's automatically visible in the sub-project. Okay, I think that's good. If this was too fast for you, then you might have a look at the Udacity course, it's about Gradle using Android and Java, so really good course, good content, well explained.
12:21
So highly recommended stuff to get over all the basics here. So what happens to our app? We have 50,000 users, we get traction. I think we have round A funding, so the glasses really work, right? Yeah, the glasses are not just fake, so that's our new office here.
12:42
Nice, looks good. I take the right side, the right wing here, I'm the left one. Feel free to come visit us, but watch out, there's our lawn, you don't want to ruin that. Great, so successful app, now we have to scale things up, right? We have a team of 20 developers, so I think we have to do a bit more work on the process.
13:07
We have to be more strict with these developers, right? And we want to extract our business logic, maybe for a web application. Might make sense to have some web presentation after all as well, right?
13:21
We want to even address the AI platform, we might do it, you know. We want to do more testing, I think, as always. Yeah, more testing and more automation, of course. We want to have a server that does all the heavy lifting and gives us reports automatically whenever something gets pushed, you know, continuous integration, quality assurance also.
13:43
Right, so we want to enforce rules on the code. Definitely, how do you do it in Gradle? Let's have a look. Yeah, first, okay, how can we make this stuff more reusable that we created? Okay, first we should have more projects, right? More modules. So it's quite easy to create a Java-only module.
14:02
So you just run this Gradle snippet we show over there. And then you can start moving your non-Android-specific code, the stuff that makes your app special. You can move that over to the newly created model project, is what we called it, right?
14:21
And then, of course, you have a dependency in your Android module because it now depends on the model project. And you move over the code, you move over the tests, yeah, it's all nice. And all that stuff that's now in the model project might be reused later on for our web project or whatever, right?
14:43
Good, and while we're at it, you know, we don't want to stop here. Yeah, we like scripting, so we know Groovy, we want to have a module where we can play with the server API or do some testing on the models or playing with the data. So let's have a playground.
15:02
Yeah, that's a Groovy module. Yeah, all the stuff that you might write scripts for, you know, Groovy is great for that. It's much less verbose than Java, so here's a little sample, just puts down the URL stuff from Google.com. So it really helps you easily try things out while you're developing.
15:23
So, good point to have a Groovy module. While we're at it, why not? Okay, so much about code, better code reuse, right? Yep, it's good, it looks better already, and maybe we pull in a web project later on, let's see. Keep continuing with the Android one.
15:40
So we have Android, the main source code, we have Android test, and probably it's a good idea to have integration test in the core module as well. So we want to separate the code for the standard unit test and for integration test. Yeah, of course, and it's quite easy, right?
16:01
What do we do? Custom source set, it's provided by Gradle, we just have to define it, it's all good. And then of course we need a custom task again, depends the test task and yeah. So now you have a new task only for your integration test. So you put every code into this folder, into this source set that deals with databases,
16:24
with connecting to the server, things like that, that you don't want to run all the time. Nice, good, good. So over time we get new updates from our dependencies and it's important for you guys to check it. Put out all these great libraries at amazing rates, and it's hard to keep up with all the latest versions of the dependencies we have.
16:45
So problem here, so how can we automate that? New plugin, I would say. More plugins to the rescue, so we pull in, what is it called? Gradle versions plugin. The Gradle version plugin, it gives you a nice report about the plugins that are available. More Gradle tasks, here's a new one, dependency updates, and gives you a nice report and yeah.
17:06
You can decide whether you want to update your dependencies or not, but it keeps you all updated with what is on JCenter and Maven Central. So quality assurance, what we wanted to tackle.
17:21
Now it gets serious, you know, rule enforcing on code, that's always a hard topic. So we add, we apply find bugs, we check and check style. We are the usual suspects, and actually this is supported out of the box by Gradle, at least for Java projects, but you know, there are some quirks with the Android plugin still,
17:44
because it's not compatible, right? Yeah, currently you can't use the check style as such, so you have to really configure it to make it work with your Android source code. And yeah, so let's configure it. Time for another custom task, right?
18:02
Yeah, custom task, but we want to configure it from a command line. So by developing, we want to have a nice report about all the issues we have with our code, but if we have a server, then we want to fail. We want to have a red build, because code is not good enough.
18:20
And we do this by adding this property, project property, and this allows you to specify a parameter on the command line. Okay, so how does it look if you run it? So you have your task, and you add the parameter, and then in your task you get the access to the project property.
18:44
Yeah, this is nice. And we want an HTML report, unfortunately check style only has XML, so we have to do something about it. Let's do add a certain execution after we have done the check style. So this is how you define scripting.
19:01
Before we had just configuration, now we have executable code that we add to our task. So you write, do last, and then whatever is in there is executed. Yeah, and we have AND support finally, again, back to XML, not quite. We can still write it nicely in Groovy, but all the AND tasks are available out of the box.
19:22
Out of the box in Gradle. So that's easy, and we have a nice report. Yeah, CI now, so we need a server, that's what we said, right? Yeah, so let's take Jenkins for now, I guess. Or Travis. And for the Travis, would be… Yeah, but we use Jenkins, so let's assume we have Jenkins.
19:44
Okay, so what we've seen earlier is that we have some properties, you know, fail fast or whatnot, that should be flipped whether we are running on CI server or running locally. So how can we detect this? And it's actually quite easy since the server sets some environment variables that we can easily check for.
20:04
And then we can just act on whether we run on a CI or not. And we can also make use of them, like the build number, for instance. So we could have a custom version name, for instance, that includes the job number, the build number of the Jenkins job.
20:20
And then we have a nice one-to-one mapping, we know which job built that APK we're currently testing, right? So that's nice. We have CI and we have lots of devices connected to our CI, we had a good funding. So we had a lot of devices, but running all the connected tests takes too much time. So we want to filter them.
20:41
How can you do that? Actually, you cannot do it with the Android build system currently, unfortunately. At least it's not a supported feature, but we have Groovy because Gradle makes use of Groovy, so we have some additional weapons under our belt, so we can use Groovy meta-programming to extend some internals.
21:04
So we take a class from the Android Gradle plugin and we modify the methods. That's cool, powerful stuff, but don't overdo it, but in this case here we did it. And we had some additional filtering, so we end up with fewer devices,
21:22
we don't want to run on tablets in this case, and we only want to run on one device per API level. And all this is possible here, and this is also a nice use of Groovy's safe navigation operator here, this is a question mark dot, and this makes sure that you don't run into null pointer exceptions
21:43
if some of the methods in between this chain here return null. So it's quite nice, quite dense, clean code, I like it, you know, it's cool. Just to explain, so this local devices is a class variable. So if the Android Gradle plugin is changed, maybe they rename the variable name, and this will fail.
22:05
Yeah, so it's a hack, of course. It's a hack, but while you're on the same build number, then your build won't fail. Yeah, it's nice that you can hack at that kind of stuff, I like it. Okay, now we have defined the task to filter our devices,
22:22
and we want to execute this filter task before we run the connected Android test. So, easy task for Gradle, right? We just ask it for, give me all the tasks you have, and then filter by those that are related to connected Android tests,
22:42
like this, and then for each of them, nice use of the spread dot operator here of Groovy again. Then we say, okay, you depend on our custom task now. So, you get the list of connected Android test tasks, and before each one, you execute this. And then this after evaluate, what is it about?
23:03
Well, you know, some of these, or maybe more or less all, I guess, of these tasks are created by the Android build system, so they are not there upfront, they are created later on, and at the after evaluate phase of the Gradle build, they are eventually there, so we cannot check for them right away when the build script gets read in and evaluated.
23:29
We have to wait until the evaluation phase has finished, and then we find all the tasks there. So, it's a nice little listener concept of Gradle. So, you have the three phases for your build script, and in the second one, the Android plugin generates the task,
23:48
and the after, you apply this method, so they are all there, and then execute this stuff, that's what we see. Okay, nice. So, CI set up, now we want to release from CI, just the red button.
24:02
We want that release me button, right? So, how far off are we of that? Okay, we need some custom versioning handling, right? We need automated updates, so we need to commit the changes, commit automation, pushing back to our repositories, and then, of course, we need
24:21
to upload automation for the Play Store stuff we had to deal with earlier. So, how do we go about that? So, the version, we wrap in a class, so have separate of concerns, and we just want to have a task that increments the version. So, let's say we have a version class, and the method to increment, this is a task.
24:46
But then, where's the class? How do you do it? Where does this custom class version would go here that handles our version scheme, right? And there's actually a nice little concept in Gradle, you know, Gradle can, you can define a build source folder,
25:01
and whatever you put under that folder, it can be a separate Gradle project, that then gets built, and the result gets put on your build time class pass, so you can use all that stuff that's built inside this project during your build. So, that's the ideal place to put your custom logic in there, and as you see here, we just create a custom Groovy class, of course, because, Groovy?
25:27
Yeah, the important thing is the name, so it really depends on the name. You have your Java Android code in a source file, and now you have a build source folder with all the code that is available during your build.
25:43
During your build. So, we have a class, but we don't want to code everything ourselves, so let's use a Groovy library. How do you do that? For Git commit, for example. So, there's this Java library called JGit, which is part of the Eclipse foundation, I think,
26:06
and there's a nice little wrapper around it, because it makes it less bloated if you have a Groovy wrapper, so we include this one, and then we have the usual commands, and we can just commit our version changes, create a nice little commit message, even, we forgot to mention that we have this nice
26:25
in-string variable replacement feature in Groovy, it's called Groovy strings, so this is nice as well, and then we push back, and it's in our source code repository. So, we have automated Git commits, that's cool. Problem solved. Next problem, please.
26:43
Upload to Google Play. Yeah, that's good. So, there's a plugin, again, you just reuse it. Yeah, more plugins, I like that, good. The TripleT plugin is quite good, we would say. It provides a list to get all the data from Google Play that is already there, that we have provided at the first release, and then it has tasks to upload the APKs,
27:07
and also updated metadata, so that's good. We have to configure a bit, give some credentials, how, yeah, you can do it. So, give some credentials, how you access Google Play,
27:24
and if you go to the website from the plugin it explains, you have to go through three, four steps once, but once you've configured, it's working nicely. So, from your command line, you can publish to Google Play. Okay, awesome. So, push button release functionality, finally.
27:41
Actually, we have two buttons, yeah? For the free version, and for the paid version. True, maybe we don't need the free version later on, because, you know, we have a big office, so we need that money. For each flavor, we have two different tasks, so we can release them, and we want to explain a bit how it's done, yeah?
28:03
So, you have all the variants, so that's the cross product from your build types, and the build flavors, so these are the variants, and you have access to them through the Gradle plugin from Android, and then you iterate through them, and you do a certain thing.
28:23
So, in this case, we want to create metadata for the oneplatform.org, end of advertisement. So, we want to create metadata, and, yeah, we don't want to explain the thing. No, no, we want to explain here. Oh, okay, sorry, too fast.
28:42
So, we wanted to explain the all. So, why do we do all? Actually, yeah, the all is some, the all operation, is it an operator, is it a method, I don't know? So, instead of each, which is just a for loop, we use all, and all is, it adds a hook to your methods.
29:03
So, whenever I have a new variant, the code that I have written there is added to it. So, you don't have to do the after evaluate, but you just add this hook, and whenever a new task comes along, then this one is executed.
29:21
Right, so it basically says, in a list for all the stuff you have here, execute this logic, so for each, and then if there's new stuff added to this list, then please execute it for the new stuff as well, so it's kind of a listener concept. Okay, good, yeah, this is nice as well.
29:40
I think that's good, we have our application in the store, now we can play a bit more. We have, how much time we have left? Twelve minutes. Good, so we have prepared some more advanced stuff. Yeah, so, best practice, best practice is your program, your application grows,
30:01
you know, you have more and more sub-projects maybe, and of course there's some common stuff that you want to share, be it for instance, code style rules, in that example or whatever, and for that you can create a method like this one here in the root project for instance,
30:20
and only this method knows where to find common resources, and then in your sub-projects you just use this method to resolve the actual location of your shared resources, and this gives you a nice decoupling from the actual physical location of your resource. So you're good to change the path without modifying all the sub-tracks,
30:42
and you can do the same with versions of your dependencies, you define it once in the root, and then you have access to the variable in your sub-projects, so that's good practice. And you can even group these together then, which is nice maybe for testing, if you have always JUnit test together with Mockito,
31:02
then you can create a group like testing dependencies, and then in your sub-projects you only say, okay, test compile depends on testing dependencies. Shrinking, now it gets…
31:22
We have a big app again, we hit the 64K method limit, I hope you don't do that, I have to deal with that too early, but if you have to deal with it, then there are some things you can do, especially if you hit it only for your debug build, because you pull in maybe big dependencies, in this case here you might pull in Guava only for some of its functionality,
31:46
and also you might strip out all the stuff you don't actually need, and you can quite easily do this with Gradle, and some utility Gradle task that's provided by the ProGuard framework, and then you just configure it, give it the right inputs, outputs,
32:04
and then it can create a custom version of Guava for you that is much smaller, because it only keeps the stuff that you specify in this special ProGuard keep statement. So it's a way to reduce your method footprint.
32:22
You also maybe want to do more with your devices during the connected Android tests, you can use everything around ADB, and the Android command plugin allows you to handle the files on the device, so it wraps what you do with pull, fetch, push and pull with ADB.
32:44
In this example, maybe it's not too close to your project, because it's just syncing some images you might have on your phone, it syncs it to your development machine, and it really only syncs those ones that are not yet on your development machine,
33:00
so it's quite nice, you can all do it with nice little groovy niceties. I like it, it's cool. So the files task defines, you need to configure the files task with the device ID, so you know I'm speaking to this device, and then whatever is in the script configuration as closure is executed on that device.
33:26
So it's also good. You have to work with databases, SQLite is supported out of the box with Android,
33:40
so it's the first place to go here, and if you have existing databases and you have to work with them, then you usually end up having the database schema information replicated in your Java code, and that's the classic case where you might use object relational mappers, but if there's an existing database,
34:01
then you cannot do that because the database is already there, so you need some database first approach, and there's a plugin called SQLite Analyzer that's working with that. It takes a database, analyzes it, creates a model from its schema, and then it allows you to create custom Java access code for that database,
34:23
so that you don't have to replicate the information, like the table names, the column names, and specific types of each column, so it can all be generated, and the best part about it is that the code that gets generated is actually fully customizable
34:40
because it's just a groovy template, and only the model of the database is fed into that template, and you can create whatever you want, whatever your needs are. If you are only interested in the table names for some weird reason, I don't know, you can just do it like this, that's all you have to do, but if you want to generate more, you can do it,
35:03
and there's default templates provided as well. And how the plugin works, it hooks into the Android build system, so that's an example where you can say, okay, now I'm before the compile task, I need to generate some code,
35:22
and then only after this task was executed to do the analysis of the SQLite database, thereafter you do the compile task. Right, so this is actually quite nice, a nice thing about the Android build system, you can just say, hey, I have a task, this task generates code,
35:40
and please execute it at the right time, and the Android plugin makes sense of it, and your generated code is then also made visible inside Android Studio, which is nice, you can have a look, debug it, whatnot. Yeah, next. Oh yeah, finally.
36:01
Yeah, you can do Groovy in your build script, but you can just take Groovy and create your Android application. So there is an Android Groovy plugin, that allows you to build your activities in Groovy script, and it's not just a play, so there are real apps out there,
36:21
the New York Times app, they use the Android Groovy plugin to create an app only in Groovy things. So there's not only Kotlin as an alternative, you can also try Groovy if you want to, and it seems to work well, at least for the New York Times. Yeah, but you have to be careful, you can't do the meta class modification,
36:42
so only the static features of Groovy can be used when you build your Android apps. Right, but you still have closures, it feels a lot like Java 8, you have these nice functional paradigms, so why not? So, I think that's... We've covered a lot of stuff.
37:02
We have collected all the plugins that we mentioned in the order of appearance, so we wanted to provide a good resource just to go back to the slides and read about what we said. And some final words, some final thanks
37:22
to the Android Stammtisch Berlin, which had to deal with most of the topics that we present here earlier, and we kind of tester drove this talk, so it was tester first approach, and it's some new technique, we call it TDTD,
37:51
and maybe we even end up writing a book on it, but that's not certain, spoiler alert here. Okay, that's all we have, thank you for your attention.