SHIIIIIIIP IIIIIIT!!1!1!!

When I joined AsanaRebel, I picked up the project and I started to navigate through the repository, focusing especially on the build.gradle file.

Sadly, I had no CI setup to understand how to build the project on one side and, on the other side, I was facing 3 build types and 4 flavors, with not even a single line of documentation. Discomfort.

The plan: simplification

Simplification is the most complex thing to do

but I could count on a highly motivated QA team and I wanted to empower them even more, enabling them to take control on the Android release process.

My first goal was to automate the release process as much as possible, because I wanted to focus more on developing the app itself, having a lot of features to catch up with, compared to the iOS app.

As usual, when I approach new projects, the first step was to make sense out of the build.gradle file.

SPOILER ALERT ⚠️

No joy there! 🤦‍

The good news was that when you are the only developer, there is no documentation or nobody to ask, and you are working for one of the fastest growing startup in Berlin, if you can’t make sense out of something in your project, you have any right to kill it. I mean it!

You are responsible for the code base, you are the one accountable for the status of the app, you are the one who’s gonna answer to any possible Android question from now on and you can’t afford to live with an area of your domain that you don’t know anything about, you don’t know the reasoning behind those decisions, and, even worst, if something goes south, you have no idea where to start to fix things.

Long story short,

Ciao ciao flavors

The current setup has two build types: debug and release. That’s it. No more releaseStaging or debugMockProduction nonsense:

KEEP IT SIMPLE, STUPID

Build server

I wanted a CI, of course. It’s a invaluable tool for any modern project and, with the plan to add more developers to the team, it was a necessary step to move forward with the right attitude: automation, safety nets and quick response.

Attempt #1: Circle CI

CircleCI was the first service I tried. They had a free tier so I could play around a bit and figure out scenarios.

It wasn’t nice, unfortunately.

The first pain point was the setup. They were, and probably still are, using a .yml file to setup the build workflow. This means that before being able to start building your project, you need to look for documentation, tutorials and examples by those who came before you and were kind enough to put that on writing. Painful.

Once you have the first draft of yml, you can start experimenting:

  1. Change something
  2. Commit and push
  3. Fingers crossed 🤞
  4. Build failed
  5. Go to 1

The Try&Error almost drove me crazy and generated this sort of git history:

CI related Git commits

You can guess my frustration. Eventually I managed to setup a successful build… kinda. I had to simplify a lot because the docker containers were failing due to not enough memory 😔

The free tier limits the available RAM in the container to 4GB, so I couldn’t run lint and anything else that would suck RAM, but at least, I had a CI.

Let’s connect it to Slack now to get build notifications!

Well, there was no ready-to-use solution available, so I had to come up with a Gradle task and some curl commands to pull the data from CircleCI and push it to Slack via Slack API. Here is a snippet:

https://gist.github.com/hamen/8c21905bfec30539a776d4975e42ca65

The whole setup was working, but it was a bit flaky. Builds were still failing every now and then due to the memory problem in the container so I decided to look into it and we decided to switch to the premium plan to enable up to 8GB RAM containers.

I was pretty happy: after weeks of struggling, I was finally going to have a proper CI. Well, not really. We hit a blocker due to some undocumented change in the pricing in CircleCI. The premium plan was gone, replaced by a Performance plan with a different price bla bla bla with different performance yabba yabba…

I was pissed for the wasted time and wasted money so, living in a free world with a free market, I turned to another service.

Attempt #2: Bitrise

I created a Bitrise account, I linked GitHub. I started playing with the website and 20 minutes later I had a fully setup CI. FFS!!

No configuration file, no bullshit.

The GitHub hook allowed me to create triggers and connect triggers to workflows. Our current triggers setup is based on 4 branches:

  • master
  • develop
  • feature/*
  • hotfix/*

These triggers fire different workflows:

  • masterDeployAlpha
  • developDeployInternal
  • feature/*BuildStaging
  • hotfix/*BuildRelease

I trust your ability to infer what’s going on here, but still, let’s put some detail in. We are using Git-flow so master contains the current production release. This means that we only merge to master when the QA team and the PM give us the 👍

Once we merge to master and push it to GitHub, Bitrise kicks in:

  1. DeployAlpha workflow starts
  2. The CI pulls master
  3. It runs gradle assRel
  4. It deploys to the Google Play Store Alpha Channel
  5. It sends a Slack message to notify QA and Support team when the new build is available.

Something similar happens pushing develop, but the build ends up on the Internal Testing channel of the Play Store where I have a handful of brave colleagues that at willing to try these Internal builds. They like to live dangerously.

I also like to live dangerously

Once the new release reaches the Play Store, my work as a developer is complete and the ball is in Antonia Landi’s back yard. She is in charge of the release process: final QA approval, Alpha/Beta/Production staged roll-out, Play Store listing management and overall quality monitoring.

If something goes south, she’ll knock to my door and we start the whole process all over again.

Take aways

Having a releasing pipeline that you can trust is an incredibly powerful asset to guarantee speed, quality and resilience:

Happy releasing, people 😉

Kotlin DSL Gradle files, multiple modules and shared variables

This doesn’t want to be a real article, but more a crash course about Kotlin DSL for Gradle.

The crucial point is the possibility of migrating an existing project to the new Kotlin DSL for Gradle, in an incremental, modularized fashion.

Below we have a pretty standard root project build.gradle file:

https://gist.github.com/hamen/7fa25a3a7ad8452873051f7782c77db5

The parts that I want to highlight are those shared version numbers, i.e. rxJavaVersion, timberVersion and so on.

This is a standard build.gradle file for an Android Library Module:

https://gist.github.com/hamen/1961a93d56d4f976b5892f3149991e58

As you can see, we reference those constants.

If you want to migrate this file to the new Kotlin DSL, you need to create a build.gradle.kts file in place of your build.gradle one and make it look like this:

https://gist.github.com/hamen/b906ad200fc94fb6f3be761b22f8fbb7

Notice how we can access those constants in a different way, but still pretty straightforward.

You will also notice that the dependencies are not the same in the two files, some versions are hardcoded, other are referencing the global constants.

It’s messy on purpose: this is an working example from one of my projects and I want to show a few of different choices you can have in those files. It’s up to you.

If you want a better overview about Kotlin DSL for Gradle, I would suggest the good article by Antonio Leiva https://antonioleiva.com/kotlin-dsl-gradle/.

Thank you all for the feedbacks and the support!

Happy Kotlin ❤️

Push vs Pull: air conditioning system

By Ivan Morgillo, Sasa Sekulic and Fabrizio Chignoli

This article has been excerpted from Grokking ReactiveX.

After a life of imperative programming, switching to a reactive mindset could seem challenging:

“Why should I give up all the control and bend to this <data are in control> thing?”

Let’s look at it in an everyday life scenario: the air conditioning system. Today is a hot day and we want to start the AC system when the temperature in the room reaches 77F. We need a thermometer.


Well, we need a Thermometer class that provides a temperature() method to obtain the current temperature in the room.

Once we know how to obtain the current temperature, we can combine it with our AirConditioning class.

This class provides three methods:

class AirConditioning {
start()
stop()
isRunning()
}

To change the status of the air conditioning system, we can use start() and stop(). If we want to check if the status change was successful, isRunning() gives us info about the current status.

Now that we know the current temperature with temperature() and we can turn on the Air Conditioning system with start(), we can create an AirConManager class with a basic monitor() method that will contain the logic needed to retrieve the current temperature, evaluate a condition and execute the proper action:

fun monitor() {
while (true) {
if (thermometer.temperature() >= 77 && !ac.isRunning()) {
ac.start()
break;
}
}
}

The current implementation of the monitor() function is almost offensive and I will understand if your eyes start bleeding:

  • we have a while(true) loop to keep on evaluating the condition;
  • we have the if condition itself that retrieves the current temperature, checks if it’s lower than 77 degrees and if the Air Conditioning system is already on;
  • we have the action block that starts the Air Conditioning system and ends the loop.

So far, we don’t have any special requirements and we don’t care about details like stopping the system or restarting the loop if the temperature drops.

This function could be refactored and polished in a few ways, but the key point will still be:

Constantly checking the temperature and deciding what to do accordingly


How could we migrate to a reactive scenario?

In an Rx oriented scenario, our thermometer would be an observable thermometer, represented by an ObservableThermometer class.

The ObservableThermomenter class will provide a single method: rxTemperature(). If we subscribe to this Observable we’ll receive the current temperature every time it changes:

fun rxTemperature() : Observable<Int> {
[...]
}

We can go back to our AirConManager and refactor it to handle out new reactive thermometer.

AirConManager can subscribe to ObservableThermometer in its monitor() method and receive a new temperature value:

void monitor() {
rxTemperature()
.subscribe(temperature -> {
if (temperature >= 77 &&!ac.isRunning()) {
ac.start()
}
})
}

Note: This .subscribe() method has a Subscriber implementing the onNext() method as a lambda expression. Subscribers usually have three methods, but if you don’t need to be notified when the stream completes or you don’t want to manage possible error scenarios, you can avoid implementing onCompleted() and onError().

The moment we subscribe, the data will start coming to us: the onNext() will receive a temperature value, we’ll evaluate it and act accordingly.

“Wait a second! All this fuss to save me a while loop?”

One of the key principles of reactive programming is that it is all about data being in charge, being able to create the perfect data stream you need and working with the stream that is available.

Let me introduce you to the .filter() operator!

Push vs Pull: create the flow you need

In our scenario, we don’t need a temperature value every time it changes. We just need to know when the temperature reaches 77F to start the Air-conditioning system. Rx is all about flowing data, coming to us to be used, filtered and transformed.

Let’s improve our monitor() method to create the sequence we need by filtering out all the temperature values we don’t need:

fun monitor() {
rxTemperature()
.filter(!ac.isRunning)
.filter(temperature >= 77)
.subscribe(temperature -> ac.start())}

As you can see, filter() evaluates a Predicate and propagates the item only if the condition is satisfied.

We were supposed to receive a new temperature value in our onNext() every second, but what we wanted was instead to get into the game only if the Air Conditioning system was off and the temperature in the room was higher than 77F. We used filter() to filter out all those scenarios we weren’t interested in and receive only the values that match our use case. We created the perfect sequence for the task at hand from an initial generic sequence that we can’t control.

This is the power of the Push approach: data coming to us. We can focus on using the data instead of retrieving and managing them.

If you’re interested in learning more, download the free first chapter of Grokking ReactiveX and see this Slideshare presentation for more details and a discount code.

If you enjoyed this article, please click the 💚 below and spread the Rx love 😊

GDG Geneva — July event

GDG Geneva is a small GDG, but we try hard 😊 Last Monday we had our July event, and, despite the tremendous heat, spent more than one hour talking about MVP on Android.

I prepared a small Android app to demonstrate how we can create an app that fetches data from a backend and shows them in a list, using two different design approaches:

  • !Good Old GOD Activity
  • MVP

Both versions are identical from a user point of view: same UI, same UX. What’s different is the code quality and maintainability, of course.

GOD Activity

Everything is in the Activity, because… why not!?

It’s easier and quicker to have everything in one place and if I need a Context I can use this.

The Retrofit network call is synchronous and we dodge the NetworkOnMainThread exception using an AsyncTask. The API client is created in the Activity, like every other needed component.

If you are like me, this approach keeps you awake at night or, even worse, gives you nightmares the moment you close your eyes.

MVP

Model-View-Presenter is the new standard de-facto on Android. In this version of the app, I tried to make the view as dumbest as possible, move as much as possible away from it and into a pure-Java codebase. Being pure-Java, we can easily test it without firing any Android device or emulator or using Robolectric.

I used Dagger2, RxJava, ButterKnife also to give an overview about common Android dev tools. Kotlin has been used in the test environment to show how you can start using the new language (read Our Savior) just for your tests and then move to a full Kotlin code base when you feel ready.

Source code

App source code is available here:

https://github.com/hamen/from-god-activity-to-mvp

Slides

Slides are available here:

https://docs.google.com/presentation/d/1bLpctfV1vjXUeQbjMTdPHQa2bdVP99FJnU8yQM_MnNs/edit?usp=sharing

My week at Droidcon Zagreb and App Builders

Last week was quite intense for me. For the first time I had two conferences in two countries in 3 days. I’m definitely too old for this 😜


Droidcon Zagreb

Droidcon Zagreb started like this:

The moment they dropped us at the hotel, we got a bag full of gifts and candy!

There were plenty of interesting talks and I perceived that the general code quality level in the Android community is increasing. Rx is getting very popular: not considering my talk and Sasa Sekulic’s one, also Mouna Cheikhna from BlaBlaCar talked about how they use Rx in their Android app:

Florina Muntenescu showed how to use RxJava for MVVM:

If you are wondering, yes, more than 25% of the speakers were women. This shows how much Droidcon Zagreb is working in the right direction: kudos, folks!

Another topic than seems to be quite accepted in the community are MVP and MVVM: finally they are widely used, for better app design and to improve testability.

This is definitely my favorite takeaway from Droidcon Zagreb: Use the right tools! Don’t be afraid of trying and failing, experiment, challenge the old ways, have fun!

App Builders

I’ve been living in the Geneva area for a few months now and I’m always looking for developers to talk to and share experience with. I created the Google Developer Group Geneva and I started attending Swiss conferences: Voxxed Zurich a few weeks ago and the newborn App Builders this past week.

App Builders was quite different from the other conferences I’m used to. I usually attend Droidcons and Java oriented conferences. App Builders was all about apps, no matter on which platform — Android, iOS — or technology — Java, Swift, C#.

Being a cross platform conference, the atmosphere was different from a typical Droidcon: attendees and speakers came from different backgrounds with different experiences to share.

The technical level of the talks was high, as expected, but something that pleasantly surprised me were the non-technical talks: I saw very few of them at Android conferences. At some point, it was like being at a TEDx event: very inspiring!

The Android track was full of interesting talks and I met a few new GDEs… all Spanish 😀

This was the first edition of App Builders and I think it was a great conference. The final touch was the github repo for slides, videos and feedback https://github.com/swissmobidevs/appbuilders16 . I love it 😀

Takeaways

iOS developers seem a little bit happier than Android developers

They surely are very fond of their platform, but they suffer Xcode 😁 (however, they have an alternative with JetBrains’ AppCode). They don’t struggle to support all those glitchy Samsung devices, because… well… they have to deal with just a couple of phones and tablets. They don’t need to support old devices and OS versions because they simply don’t exists: 95% of the market runs the latest or the previous version of the OS and that’s it.

Most of them migrated to the new language, Swift, the moment it went out, while most of us are still complaining about how Kotlin is 2% slower at build time, but if you ask me, a modern language that allows you to create more elegant and more readable code it’s just worth the longer build time, because you build it once, but you have to read and maintain it for months!

A lot of iOS devs envy our Google Play Store rollout feature, alpha/beta channels and stats, but at the same time they managed to overcome the problem, as Spotify and others do:

I think we can learn a lot from the iOS community. We should complain less and act more, we should be braver, jump on the next new thing, try it, embrace it and push it to our companies if we like it, instead of waiting that the thing gets mainstream and everybody else is using it already. We must experiment more, instead of following others.

We should be able to influence the way manufacturers address the market, through a sensible feedback on how difficult it is to support 2+ years old versions of Android, on dozens of different models. If we stop supporting 3 years old Android versions, maybe manufacturers will start thinking about keeping their devices updated. Who knows?!

If we start using Kotlin today as our main language on Android, we will be able to have an impact on future improvements of the language itself, and on the enhancement of all the development tools we’d love to have and, maybe, getting Google involved, for the future of the Android community, for the greater good.

Happy coding 😊

Running Android Unit Tests before Git Push

This is a quick note about a Git hook I use to double check that everything is fine before pushing to our remote Git repo.

This covers a paranoid scenario, I know, but sometimes a refactoring can go wrong and lose pieces between production code and tests: every now and then, one of my tests goes out-of-sync and when I push to Github/CI, I get some silly error because of a typo somewhere. This trick will re-run every Unit Test when I give git push and will actually push only if tests pass.

The Script

Create a file named pre-push and place it in your_repo/.git/hooks . Be sure the file is executable: chmod +x pre-push

Copy this snippet into the file:

https://gist.github.com/hamen/f080a06b6283c61da637cf81388f4b4e

This uses ./gradlew clean test, but you can use ./gradle check or any other Gradle task you use to run your tests.

Conclusions

Git hooks are quite handy in lots of scenarios and there are plenty of them. Check out http://githooks.com/.

Personally, I find pretty useful my pre-push hook and, obviously, lolcommits! 😀

Android Library AAR and Javadoc

As an Android developer, I’m used to ask Android Studio/Intellij Idea for documentation constantly. I have even replaced the shortcut: now, it’s F1, the old-fashion help key. When I want to know about a method or a class, I hit F1 and the JavaDoc shows up: smooth. How does this works? Story time!

The Catapush user

Could you point me to the new method when a method gets deprecated. It’s easier for me to replace the old API this way.

And I was like: WTF!? I hate when this happens to me and that’s why I’m taking the time to save the hassle to Catapush users!!! The method is @Deprecated and there is a nice “Please, use this other method” in the Javadoc. I see it! It’s here! Why is he telling me there is no JavaDoc!? And then it hit me…

ME: Are you saying that AAR files don’t contain JavaDoc?

HardReality: Yes, Ivan, little naive Android developer

Most of the time, during your Android development, the documentation shows up because you are using open source libraries. Our IDE retrieves the sources.jar file under the hood and shows the JavaDoc directly from the source code.

Catapush is closed source (for now 😉 ) so we are only distributing the AAR file using Jitpack. AAR means no JavaDoc in the library. No sources.jar means no JavaDoc retrieved from the source code.

HTML JavaDoc

As first step, I tried to create an HTML version of the JavaDoc just for the sake of having it published. With Jitpack, this is a no-brainer. Simply add this to your build.gradle:

task javadoc(type: Javadoc) {
failOnError false
source = android.sourceSets.main.java.sourceFiles
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
}

// build a jar with javadoc
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}

artifacts {
archives javadocJar
}

Push your library to Github, build it with Jitpack and you will have your HTML doc at https://jitpack.io/com/github/USER/REPO/VERSION/javadoc/

Problem solved! No! I find HTML doc unpractical. I want it in my IDE.

The Interface trick

The only way to have doc in the IDE is to distribute it as source code. When you work with closed source libraries, this is not an option, but… you can publish a part of the source code.

I extracted interfaces for every class that is part of the public API of the library and I documented the interfaces, instead of the implementations.

public interface ICatapush {

/**
* Initializes Catapush
*
*
@param context Application Context. Catapush should be initialized in your class that extends Android Application,
* passing <b>this</b> as {
@link Context};
*
@param callback You can receive a callback call when the initialization is completed.
*/
void init(@NonNull Context context, @NonNull Callback<Boolean> callback);
/**
* Starts Catapush. This is the final method of the chain.
* Be sure to call this after {
@link #setAppKey(String)},
* {
@link #setUser(String, String)}, {@link #setPush(Notification)} and {@link #setGcmSenderId(String)}.
*/
void start();
}

Once every interface was documented, I could publish the sources.jar via Jitpack, with a few lines in my build.gradle:

// build a jar with source files
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'

include("**/ICatapush.java")
}
artifacts {
archives sourcesJar
}

Sync, push and build and you are done! Every time you import Catapush in your project, Android Studio/Intellij Idea will retrieve the sources.jar under the hood and, when you ask for documentation, the magic will happen:

Javadoc copied from the Interface to the implementation

Our IDE is smart enough to inherit the Javadoc from the interface when we ask it on the actual implementation.

Conclusions

Extract a few interfaces, add your Javadoc, add a few lines to your Gradle file and you are good to go. Documentation is important for your users and your co-workers: don’t let them down.

I don’t really know why there is no support for documentation in the AAR format and, right now, it doesn’t matter anymore:

Android community, like Nature, always finds a way.