<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Guillermo Orellana</title>
    <description>May contain traces of sarcasm and siesta</description>
    <link>https://guillermoorellana.es/</link>
    <atom:link href="https://guillermoorellana.es/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Fri, 12 May 2023 12:56:22 +0000</pubDate>
    <lastBuildDate>Fri, 12 May 2023 12:56:22 +0000</lastBuildDate>
    <generator>Jekyll v3.9.3</generator>
    
      <item>
        <title>Maintaining and restoring window arrangements in MacOS</title>
        <description>&lt;p&gt;Frustrated about your MacOS forgetting all your beautiful screen arrangements? Dealing with the neck pain of so much head tilting searching for where the screen settings are? This page is for you.&lt;/p&gt;

&lt;h1 id=&quot;install-homebrew&quot;&gt;Install Homebrew&lt;/h1&gt;

&lt;p&gt;Go to https://brew.sh/ and follow instructions&lt;/p&gt;

&lt;h1 id=&quot;install-displayplacer&quot;&gt;Install displayplacer&lt;/h1&gt;

&lt;p&gt;Instructions from the GitHub repo are&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew tap jakehilborn/jakehilborn &amp;amp;&amp;amp; brew install displayplacer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;copy-your-layout-configuration&quot;&gt;Copy your layout configuration&lt;/h1&gt;

&lt;p&gt;After installing the tool, execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;displayplacer list&lt;/code&gt; in a terminal. Copy the output, that will look something like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;displayplacer &quot;id:0BF37642-C36D-6E90-01B5-9C8D747DA7F5 res:2560x1440 scaling:off origin:(0,0) degree:0&quot; &quot;id:E8102887-70FC-9A98-8839-157ACFB40B52 res:1440x2560 scaling:off origin:(-1440,-404) degree:90&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;create-a-quick-action-in-automator&quot;&gt;Create a Quick Action in Automator&lt;/h1&gt;

&lt;p&gt;Open Automator, and create a new Quick Action. If you can’t find Automator, you can do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd+Space&lt;/code&gt; and type its name.&lt;/p&gt;

&lt;h2 id=&quot;add-a-run-shell-script-action&quot;&gt;Add a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Run Shell Script&lt;/code&gt; action&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/172084/71083415-47fea000-2193-11ea-9461-b8b5e7b948e9.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;paste-the-output-of-the-layout-configuration-step&quot;&gt;Paste the output of the layout configuration step&lt;/h2&gt;

&lt;p&gt;Put an absolute path to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;displayplacer&lt;/code&gt; if you have issues with the shell path (if it complains about not finding the displayplacer executable)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/172084/71083582-ac216400-2193-11ea-986e-13434bea8109.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you need to know the full path to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;displayplacer&lt;/code&gt;, execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;which displayplacer&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;save-the-quick-action-and-give-it-a-memorable-name&quot;&gt;Save the Quick Action and give it a memorable name&lt;/h2&gt;

&lt;p&gt;Memorable as in you will have to find it later in a different place.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/172084/71083725-f9053a80-2193-11ea-89d4-337be7bd42e4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;create-a-shortcut&quot;&gt;Create a shortcut&lt;/h1&gt;

&lt;h2 id=&quot;open-shortcut-settings&quot;&gt;Open Shortcut settings&lt;/h2&gt;

&lt;p&gt;It’s in System Preferences &amp;gt; Keyboard &amp;gt; Shortcuts&lt;/p&gt;

&lt;h2 id=&quot;find-your-saved-quick-action&quot;&gt;Find your saved Quick Action&lt;/h2&gt;

&lt;p&gt;It usually is right at the end of the list, so scroll away.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/172084/71083839-41245d00-2194-11ea-811e-2ae9e9fdc211.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;assign-a-key-binding-to-it&quot;&gt;Assign a key binding to it&lt;/h2&gt;

&lt;p&gt;Make sure it’s not one that is already defined in the system (you can disable it if it is) or one that you would use regularly on your day-to-day.&lt;/p&gt;

&lt;p&gt;I’ve used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cmd+Alt+Shift+R&lt;/code&gt; but your mileage may vary.&lt;/p&gt;

&lt;h1 id=&quot;happy-rotating&quot;&gt;Happy rotating&lt;/h1&gt;

&lt;p&gt;Try it out next time your screens go bonkers and if it saved you any time say thanks!&lt;/p&gt;
</description>
        <pubDate>Wed, 18 Dec 2019 12:37:00 +0000</pubDate>
        <link>https://guillermoorellana.es/2019/12/18/restore-mac-window-layout.html</link>
        <guid isPermaLink="true">https://guillermoorellana.es/2019/12/18/restore-mac-window-layout.html</guid>
        
        
      </item>
    
      <item>
        <title>Your own personal Heroku</title>
        <description>&lt;p&gt;I’ve just finished doing a talk at the &lt;a href=&quot;https://milan.kotlincommunityconf.com/&quot;&gt;Milan Kotlin Community Conference&lt;/a&gt; about a recent pet project of mine: &lt;a href=&quot;https://keynotedex.wiyarmir.es/&quot;&gt;Keynotedex&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Keynotedex (&lt;a href=&quot;https://github.com/wiyarmir/keynotedex&quot;&gt;code here&lt;/a&gt;) is a project that I created to experiment with Kotlin multiplatform in platforms I am not that confident with, such as web and backend.&lt;/p&gt;

&lt;p&gt;One of the most frequently asked questions was “how do you deploy your server code?”. I get it, it is all nice and beautiful in the examples, but they never go over the “production” case.&lt;/p&gt;

&lt;h2 id=&quot;finding-a-home-for-our-backend-code&quot;&gt;Finding a home for our backend code&lt;/h2&gt;

&lt;p&gt;At the end of the day, your Kotlin server code is just a JAR file. You could use &lt;a href=&quot;https://docs.gradle.org/current/userguide/war_plugin.html&quot;&gt;the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;war&lt;/code&gt; Gradle plugin&lt;/a&gt; to generate a standard container you could drop in a server such as &lt;a href=&quot;http://tomcat.apache.org/&quot;&gt;Apache Tomcat&lt;/a&gt;. But that’s scary, or at least it seems like overly complicated for a pet project.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.heroku.com/&quot;&gt;Heroku&lt;/a&gt; is a PaaS that lets you deploy apps with git commands. Although more popular within the JavaScript and Ruby communities, they fully support JVM as well. Deploying your code by just doing:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push herkou master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s priceless. Actually no, there are some limitations on what you can get from Heroku for free. Your service will have some hours of runtime allowed, then capped unless you switch to the paid tier. That’s fair enough, but what if you want the flexibility of deploying from git commands, and you already have a spare server from, say, a weird Black Friday shopping rampage? (True story, by the way)&lt;/p&gt;

&lt;h2 id=&quot;enter-dokku-and-herokuish&quot;&gt;Enter Dokku and Heroku(ish)&lt;/h2&gt;

&lt;p&gt;Honouring &lt;a href=&quot;https://www.youtube.com/watch?v=i2GEOcEcRtY&quot;&gt;the Depeche Mode reference&lt;/a&gt; at the title, somebody already had figured out that question. You can install your own version of Heroku, in your own servers, and use that great workflow.&lt;/p&gt;

&lt;p&gt;There are two tools that take part in that: &lt;a href=&quot;https://github.com/gliderlabs/herokuish&quot;&gt;herokuish&lt;/a&gt; emulates Heroku build and runtime tasks in containers, and &lt;a href=&quot;https://github.com/dokku/dokku&quot;&gt;Dokku&lt;/a&gt; manages such containers using &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt;. And it’s lightweight. They claim to be “The smallest PaaS implementation you’ve ever seen”.&lt;/p&gt;

&lt;h2 id=&quot;thats-a-lot-of-devops-jargon-show-me-how-to-do-it&quot;&gt;That’s a lot of DevOps jargon, show me how to do it&lt;/h2&gt;

&lt;p&gt;Nobody is going to be able to teach you how to get Dokku up better &lt;a href=&quot;http://dokku.viewdocs.io/dokku/&quot;&gt;than their own docs&lt;/a&gt; (and those won’t go out of date as quick as this article).&lt;/p&gt;

&lt;h1 id=&quot;preparing-our-code-to-run-on-herokuish&quot;&gt;Preparing our code to run on Heroku(ish)&lt;/h1&gt;

&lt;p&gt;Even if I did go for Dokku, everything here applies to a Heroku deployment as well. I will be basing my examples on code written using &lt;a href=&quot;http://ktor.io&quot;&gt;Ktor&lt;/a&gt;. Other frameworks for some of the techniques may work, but your mileage may vary.&lt;/p&gt;

&lt;p&gt;Remember what I mentioned at the beginning, our code is bundled into just a JAR file. In theory, we could just run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java -jar server.jar&lt;/code&gt;. However, doing that will point out one thing: regular JAR files don’t really carry their dependencies over.&lt;/p&gt;

&lt;h2 id=&quot;stuffing-all-your-deps-inside-a-jar&quot;&gt;Stuffing all your deps inside a JAR&lt;/h2&gt;

&lt;p&gt;In order for our dependencies to be in the classpath at runtime, we need to carry them over and create what is known as a fat JAR or uber JAR. You will understand the naming when you check the size of that new JAR. There’s a Gradle plugin that will do it for you, called &lt;a href=&quot;https://github.com/johnrengelman/shadow&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shadow&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Applying it to our backend module will create new tasks that will take the outcome of our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jar&lt;/code&gt; task and fill it up with the classes from our dependencies. If you run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./gradlew server:shadowJar&lt;/code&gt; you will find in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build/libs&lt;/code&gt; a new JAR file with the suffix &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-all&lt;/code&gt;. That’s the one!&lt;/p&gt;

&lt;p&gt;There are lots of things you can customise in this process. If you are up for it, the best way is to create a task of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ShadowJar&lt;/code&gt;, the same way you would create one of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Jar&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As an example, this is the task I created to have a release style shadow JAR, with the purpose of adding some extra sources not present in the regular JAR.&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;releaseJar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;type:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ShadowJar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;manifest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;attributes&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Main-Class&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;keynotedex.backend.ServerKt&quot;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;classifier&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'release'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sourceSets&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceSets&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;configurations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;configurations&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since had a new task created, I had to define where my main class is. This way, the JAR file can be run from the terminal. This is not necessary if you are just using the output of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shadowJar&lt;/code&gt; task, it will pick whatever &lt;a href=&quot;https://docs.gradle.org/current/userguide/application_plugin.html&quot;&gt;the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;application&lt;/code&gt; plugin&lt;/a&gt; says.&lt;/p&gt;

&lt;p&gt;Note that the property &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;classifier&lt;/code&gt; is what will be appended to your JAR file name, so in this case a file with the name &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;backend-0.0.1-release.jar&lt;/code&gt; will be generated. Now, take a moment to test that, when running the JAR file, your server spins up.&lt;/p&gt;

&lt;h2 id=&quot;ikea-instructions-but-for-your-paas&quot;&gt;IKEA instructions, but for your PaaS&lt;/h2&gt;

&lt;p&gt;Now we are able to build a shadow JAR that contains our dependencies, but is our service able to do so? Unless we want to commit our build output (please don’t), we will have to tell our service how to reach that goal state.&lt;/p&gt;

&lt;p&gt;According to &lt;a href=&quot;https://devcenter.heroku.com/articles/deploying-gradle-apps-on-heroku#overview&quot;&gt;the official Heroku docs&lt;/a&gt; (and Herokuish follows them as expected), when it detects a Gradle project, Heroku will attempt invoke one command:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./gradlew stage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can take advantage of that and use that hook to trigger the whole shadow JAR process. You do not need to write a fully fledged shiny new task, you can just make it depend on your backend tasks like this:&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;distribution&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dependsOn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;':backend:shadowJar'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Remember, this task must be defined inside the root Gradle project for it to work.&lt;/p&gt;

&lt;h2 id=&quot;how-do-you-turn-this-on&quot;&gt;How do you turn this on&lt;/h2&gt;

&lt;p&gt;Now that the service knows how to build it, we have to tell it how to run it. In our case, we create a file at the root of our repository called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Procfile&lt;/code&gt;, which contains all the services we define and how to run them. Mine looks like this, but remember my JAR classifier is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;release&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;web: java -Dserver.port=$PORT $JAVA_OPTS -jar backend/build/libs/*-release.jar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PORT&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$JAVA_OPTS&lt;/code&gt; will be defined by the service at run time, so make sure to pass those on and use them in your code, otherwise your backend may not be able to reach the internet.&lt;/p&gt;

&lt;h2 id=&quot;ship-it-shipit&quot;&gt;Ship it! :shipit:&lt;/h2&gt;

&lt;p&gt;Write the aforementioned command, play your favourite tune, sit back, relax.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push dokku master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here is a little eye candy showing how it looks like to deploy Keynotedex:&lt;/p&gt;

&lt;script src=&quot;https://asciinema.org/a/M5Xlz2XsY7mkHfURPfQx2UQXZ.js&quot; id=&quot;asciicast-M5Xlz2XsY7mkHfURPfQx2UQXZ&quot; async=&quot;&quot;&gt;&lt;/script&gt;

&lt;h2 id=&quot;bonus-stage-easy-https-with-letsencrypt&quot;&gt;Bonus stage: easy HTTPS with Letsencrypt&lt;/h2&gt;

&lt;p&gt;Until now, both Heroku and Herokuish environments are able to do what I describe, but this one is exclusive of Dokku.&lt;/p&gt;

&lt;p&gt;HTTPS is very important, I am not even going to discuss it here. And &lt;a href=&quot;https://letsencrypt.org/&quot;&gt;Let’s Encrypt&lt;/a&gt; has enabled many people to obtain what used to be an expensive luxury: SSL certificates.&lt;/p&gt;

&lt;p&gt;Fear not, you can use &lt;a href=&quot;https://github.com/dokku/dokku-letsencrypt&quot;&gt;dokku-letsencrypt&lt;/a&gt;: a dokku plugin for automagically obtaining SSL certificates for your domain, and enabling HTTPS. And it is as easy as deploying a new version. This is how I renew my certificate in Keynotedex:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dokku letsencrypt keynotedex
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;/h1&gt;

&lt;p&gt;The Heroku style of deployment has made publishing a backend service as easy as deploying an APK into an Android phone. This is great because makes backend less scary and confusing.&lt;/p&gt;

&lt;p&gt;In addition, Dokku allows you to have full control over the system, and use it in environments where you would not be allowed to put things into a public cloud.&lt;/p&gt;

&lt;p&gt;This should not be thought as exclusive for human-triggered deployments, as this simplification will surely make systems for deploy-on-merge way simpler.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Thanks to &lt;a href=&quot;https://twitter.com/corbyjerez&quot;&gt;Jose A. Corbacho&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/Guardiola31337&quot;&gt;Pablo Guardiola&lt;/a&gt; for taking the time to review this article.&lt;/p&gt;
</description>
        <pubDate>Thu, 14 Jun 2018 12:37:00 +0000</pubDate>
        <link>https://guillermoorellana.es/2018/06/14/your-own-personal-heroku.html</link>
        <guid isPermaLink="true">https://guillermoorellana.es/2018/06/14/your-own-personal-heroku.html</guid>
        
        
      </item>
    
      <item>
        <title>Avoiding the clean boilerplate: Welcome Project Lombok</title>
        <description>&lt;p&gt;&lt;em&gt;This blogpost is from 2016. If you are reading this today, there are way better solutions than Lombok, for instance Kotlin&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Looks like nowadays, clean is the trend. Clean eating, clean lifting, clean architecture…&lt;/p&gt;

&lt;p&gt;Let’s have a look at the list of topics for the latest DroidCon in Spain:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-10-17-avoiding-the-clean-boilerplate-welcome-project-lombok/droidconmad.jpg&quot; alt=&quot;&amp;quot;Todas las charlas que menciona Clean Architecture &amp;lt;a href=&amp;quot;https://twitter.com/hashtag/CleanHype?src=hash&amp;quot;&amp;gt;#CleanHype&amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;https://twitter.com/hashtag/DroidconMAD?src=hash&amp;quot;&amp;gt;#DroidconMAD&amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;https://t.co/gvr1yMqj8o&amp;quot;&amp;gt;pic.twitter.com/gvr1yMqj8o&amp;lt;/a&amp;gt;&amp;quot; — Antonio López Marín (@tonilopezmr) &amp;lt;a href=&amp;quot;https://twitter.com/tonilopezmr/status/754348235150491649&amp;quot;&amp;gt;July 16, 2016&amp;lt;/a&amp;gt;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Notice that there is a check mark for every talk mentioning or speaking about Clean Architecture. And opposite to what it might look like, the &lt;em&gt;MAD&lt;/em&gt; in the name is not because they are MAD about Clean Architecture, but because it took place in Madrid. It is everything but a new concept, but seems to have drawn a lot of attention in the Android community during the past few months.&lt;/p&gt;

&lt;p&gt;With such a huge resonation in the community, it must be our &lt;em&gt;NextSilverBullet™&lt;/em&gt;, let us make all our code life and things clean! Layers of abstraction, pluggable, replaceable and testable components, immutable data models, one data model per layer…&lt;/p&gt;

&lt;p&gt;So after &lt;em&gt;x&lt;/em&gt; time refactoring or rewriting (where &lt;em&gt;x&lt;/em&gt; approaches infinity), we end up with &lt;strong&gt;10 times more boilerplate than actual code&lt;/strong&gt;. How did we get here?&lt;/p&gt;

&lt;h1 id=&quot;the-pain&quot;&gt;The pain&lt;/h1&gt;

&lt;p&gt;Java is a very flexible language. Some of the concepts in &lt;strong&gt;Clean Architecture&lt;/strong&gt; introduce a lot of restrictions and requirements. Such restrictions and requirements need code to be expressed in Java. Other languages may not need so much code since they allow you (or require you) to be as restrictive (like, &lt;strong&gt;Kotlin&lt;/strong&gt; and immutability), but if it’s Java what you have in your toolset, for instance to achieve immutability you need to define all args constructors, setters and builders to spice it up. Stuck with boilerplate you are. &lt;strong&gt;Or are you?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-10-17-avoiding-the-clean-boilerplate-welcome-project-lombok/refactorgenerate.png&quot; alt=&quot;Meet your new best friends, Refactor This and Generate&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;meet-project-lombok&quot;&gt;Meet Project Lombok&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://projectlombok.org/&quot;&gt;Project Lombok&lt;/a&gt; is magic made code. Or code that makes magic. Or… Well, it’s actually an &lt;strong&gt;annotation processor&lt;/strong&gt; that generates code, but instead of creating derivate clases we have to guess (I am looking at you, Dagger2), it &lt;em&gt;injects&lt;/em&gt; the generated code in our class. Told you, &lt;em&gt;Magic!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;How does it achieve its magic properties? Well, Lombok is not your typical annotation processor. Its annotations are processed at development time, injecting code so it’s immediately available for the developer. This requires some sort of collaboration from the IDE though.&lt;/p&gt;

&lt;h1 id=&quot;project-lombok-and-android&quot;&gt;Project Lombok and Android&lt;/h1&gt;

&lt;p&gt;In order to use it in you Android project, head to the &lt;a href=&quot;https://projectlombok.org/download.html&quot;&gt;project download webpage&lt;/a&gt; and get the coordinates to the latest version. If you are using the Gradle apt plugin, you might need to add its entry as well. It might look like this:&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;provided&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;org.projectlombok:lombok:1.12.6&quot;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// or latest version&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;apt&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;org.projectlombok:lombok:1.12.6&quot;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// only if using gradle-apt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Project Lombok needs little to no configuration, but there are some special cases we need to consider when using it in Android. In order to customise the behaviour of Lombok, we can put a file named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lombok.config&lt;/code&gt; in one of the roots of our project. I usually have it at the root of the module or modules that actually make use of Lombok, since we might choose not to use it in all of them.&lt;/p&gt;

&lt;p&gt;In order to comfortably develop with it, you will want to add a plugin that supports Lombok generation at dev time. In Android Studio, this can be done installing the Lombok plugin, which is available from the plugins menu.&lt;/p&gt;

&lt;h2 id=&quot;generating-way-too-many-things&quot;&gt;Generating way too many things&lt;/h2&gt;

&lt;h3 id=&quot;javabeansconstructorproperties&quot;&gt;java.beans.ConstructorProperties&lt;/h3&gt;

&lt;p&gt;Android lacks of the beans package (thankfully), so when you try to use one of the constructor family annotations, you will get a compile time error similar to this one:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Error:(9, 1) error: cannot find symbol class ConstructorProperties
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In order to disable such annotations from generating, just add this line to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lombok.config&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lombok.anyConstructor.suppressConstructorProperties = true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;javaxannotationgenerated&quot;&gt;javax.annotation.Generated&lt;/h3&gt;

&lt;p&gt;Yes, there is an annotation to say that something was generated by an annotation processor (&lt;a href=&quot;http://inception.davepedu.com/&quot;&gt;&lt;em&gt;Inception&lt;/em&gt; sound&lt;/a&gt;). Of course, there is a reason for this: Annotation processors are applied in &lt;em&gt;rounds&lt;/em&gt;, so the output of one annotation processor may be processed by other annotation processors or even by itself on further rounds! (more &lt;a href=&quot;http://inception.davepedu.com/&quot;&gt;&lt;em&gt;Inception&lt;/em&gt; sound&lt;/a&gt;). In order to avoid going too many levels deep, generated code is annotated so the processors can distinguish it and decide wether process it or not.&lt;/p&gt;

&lt;p&gt;The problem is, Android does not bundle this one either. You can go for the easy solution, which is not generating them at all:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lombok.addGeneratedAnnotation = false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Or the probably correct one, which is adding a dependency that contains this annotation to your build. Don’t worry, it’s retention is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SOURCE&lt;/code&gt;, which means it won’t go to your class files (and eventually your DEX files).&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;provided&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;javax.annotation:jsr250-api:1.0&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;comparison&quot;&gt;Comparison&lt;/h1&gt;

&lt;p&gt;Probably my favourite comparison to do is the use of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Data&lt;/code&gt; annotation. Consider this example taken from the Lombok project page:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Value&lt;/span&gt; 
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ValueExample&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;score&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Just one annotation, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Value&lt;/code&gt;, will trigger:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Marking the class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;final&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ToString&lt;/code&gt; annotation, generating a toString() with all the fields present&lt;/li&gt;
  &lt;li&gt;Like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@EqualsAndHashCode&lt;/code&gt; annotation, generating valid equals() and hashCode() methods&lt;/li&gt;
  &lt;li&gt;Like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@AllArgsConstructor&lt;/code&gt; annotation, generating a constructor with all the fields as arguments&lt;/li&gt;
  &lt;li&gt;Like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Getter&lt;/code&gt; annotation, generating a getter for each field (the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Getter&lt;/code&gt; annotation would be required at each field otherwise)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So it’s like a super-annotation (or a shorthand for all the above). This would generate &lt;a href=&quot;https://gist.github.com/wiyarmir/e8ca8c4de79ee367efbcfac9229c323d&quot;&gt;the following Java code&lt;/a&gt;. 70 lines of code generated by Lombok after writing just 7 lines. That’s 10 times the amount of code!&lt;/p&gt;

&lt;h1 id=&quot;alternatives&quot;&gt;Alternatives&lt;/h1&gt;

&lt;p&gt;Is Lombok all what is out there? Is this a crazy isolated idea? Not really, there are many other options. Let’s explore two: first, a more moderated approach to code generation, without injection. Second, if you would rather turn it up to 11, a way to inject code for even more things.&lt;/p&gt;

&lt;h2 id=&quot;autovalue&quot;&gt;AutoValue&lt;/h2&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@AutoValue&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numberOfLegs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;AutoValue_Animal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numberOfLegs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;numberOfLegs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you want a more traditional and less hacky experience, Google’s &lt;a href=&quot;https://github.com/google/auto/tree/master/value&quot;&gt;AutoValue&lt;/a&gt; does that for you. However, since it does less magic tricks, it does not feel nearly as easy to use. You need to declare your classes abstract and your values as abstract methods. It still allows you to reference the original class when instantiating, but you will work with a derived type.&lt;/p&gt;

&lt;h2 id=&quot;android-annotations&quot;&gt;Android Annotations&lt;/h2&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Fullscreen&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@EActivity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;bookmarks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@WindowFeature&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;FEATURE_NO_TITLE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BookmarksToClipboardActivity&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Activity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@ViewById&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;ListView&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bookmarkList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@ViewById&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;EditText&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@App&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;BookmarkApplication&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@SystemService&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;ClipboardManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clipboardManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;nd&quot;&gt;@Click&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;updateBookmarksButton1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;R&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;updateBookmarksButton2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;updateBookmarksClicked&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//[...]&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If code being injected is not a scary idea for you, but rather an exciting one, then why not inject &lt;strong&gt;all the things?&lt;/strong&gt; Taking the concept of Project Lombok to the next level, with &lt;a href=&quot;http://androidannotations.org/&quot;&gt;Android Annotations&lt;/a&gt; you can do things like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@SystemService&lt;/code&gt; to inject services from the current context. A bit too much for me, but always worth the try.&lt;/p&gt;

&lt;p&gt;It even comes with a REST client that reminds me a lot of Retrofit:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Rest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://www.bookmarks.com&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BookmarkClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/bookmarks/{userId}?search={search}&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;Bookmarks&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getBookmarks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@Path&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;@Path&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;userId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Project Lombok is a very powerful tool, and like all powerful tools it can get out of hands pretty quickly. But if you keep its usage down to a reasonable level, it can help you a lot to go through the most tedious parts of elaborated architectures: boilerplate code.&lt;/p&gt;

&lt;p&gt;And if at some point you decide to get rid of Lombok, you can rest assured, they provide a system to de-Lombok your code and make the generated code persist instead of the annotations.&lt;/p&gt;

&lt;p&gt;I am personally using this tool among others to help me in my rewrite of &lt;a href=&quot;https://github.com/wiyarmir/TravisForAndroid/&quot;&gt;Travis for Android&lt;/a&gt;, more on that task to come soon!&lt;/p&gt;
</description>
        <pubDate>Mon, 17 Oct 2016 13:00:40 +0000</pubDate>
        <link>https://guillermoorellana.es/2016/10/17/avoiding-the-clean-boilerplate-welcome-project-lombok.html</link>
        <guid isPermaLink="true">https://guillermoorellana.es/2016/10/17/avoiding-the-clean-boilerplate-welcome-project-lombok.html</guid>
        
        <category>android,lombok,clean</category>
        
        
      </item>
    
      <item>
        <title>RxJava - FlatMap tricks</title>
        <description>&lt;p&gt;Quick one: Have you ever had to convert one layer model to the next one, and iterate through all the child elements to convert them as well? Not saying there is something wrong with that, but with a bit of RxJava magic we can make it look so much cooler.&lt;/p&gt;

&lt;p&gt;Say you have your &lt;em&gt;VeryCleanArchitecture™&lt;/em&gt; data source&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@NonNull&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Single&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;InmojiGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;InmojiCampaignCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stuff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StuffSDK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getStuff&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;InmojiGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;networkStuff&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;InmojiCampaignCategory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stuffCategory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stuff&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;InmojiItem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;StuffItem&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stuffCategoryItem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stuffCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getStuffItems&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;NetworkStuffItem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stuffCategoryItem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;networkStuff&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NetworkStuffGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stuffCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTitle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; 
                                                  &lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Single&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;just&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;networkStuff&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Nice and easy. But it is not &lt;em&gt;reactive enough&lt;/em&gt;. With a bit of salt and pepper, we can make it look &lt;em&gt;VeryCleanMuchReactiveArchitecture™&lt;/em&gt; worthy. However, notice that we need to access to some property of the original parent to compose our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NetworkStuffGroup&lt;/code&gt;. A simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt; won’t do it, since we would only have access to the child items.&lt;/p&gt;

&lt;p&gt;But what about doing like this:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@NonNull&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Single&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;NetworkStuffGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Observable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;StuffSDK&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getStuff&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;stuffCategory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;Observable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stuffCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getStuffItems&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
                    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;NetworkStuffItem:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stuffCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;networkStuffItems&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 
                &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NetworkStuffGroup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;stuffCategory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTitle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; 
                    &lt;span class=&quot;n&quot;&gt;networkStuffItems&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toSingle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;What the heck was that? Calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt; with two arguments? Well, it is not straightforward, but &lt;a href=&quot;http://reactivex.io/RxJava/javadoc/rx/Observable.html#flatMap%28rx.functions.Func1,%20rx.functions.Func2%29&quot;&gt;one of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt; overloads&lt;/a&gt; has a resultSelector as a second parameter.&lt;/p&gt;

&lt;p&gt;We can use as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resultSelector&lt;/code&gt; a function that takes the item before the flatMap and the grouped collection after the flatmap. This way we can easily create our network model group, without any confusing usage of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&amp;lt;T,U&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And that’s all folks! May your code be reactive and your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Observable&lt;/code&gt; never randomly unsubscribe.&lt;/p&gt;
</description>
        <pubDate>Tue, 27 Sep 2016 08:00:40 +0000</pubDate>
        <link>https://guillermoorellana.es/2016/09/27/rx-java-flatmap-tricks.html</link>
        <guid isPermaLink="true">https://guillermoorellana.es/2016/09/27/rx-java-flatmap-tricks.html</guid>
        
        <category>rxjava,java</category>
        
        
      </item>
    
      <item>
        <title>How to convince your PM into refactoring tests</title>
        <description>&lt;p&gt;I know, the two words your (Product Owner|Product Manager|Project Manager) hates the most, &lt;strong&gt;tests&lt;/strong&gt; and &lt;strong&gt;refactoring&lt;/strong&gt; together! Those don’t burn points in the chart! Am I trying to make them have a heart attack? Well, not really. It all depends on how you pitch the idea to them.&lt;/p&gt;

&lt;h1 id=&quot;the-case&quot;&gt;The case&lt;/h1&gt;

&lt;p&gt;For instance, if we take a test file with this header:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-08-16-how-to-convince-your-PM-into-refactoring-tests/androidtest.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It is recognisable that this is an Android Instrumentation Test. Nothing wrong with them, but I believe RxJava has nothing to do with the Android framework itself, so why is this an instrumentation test? I can think about many reasons. Legacy structure, old build tools, inertia… But we can do better now.&lt;/p&gt;

&lt;p&gt;What about this other header:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-08-16-how-to-convince-your-PM-into-refactoring-tests/junittest.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can quickly spot this is the same class, but is now running as a pure JUnit test. Why even bother doing it?&lt;/p&gt;

&lt;h2 id=&quot;speed&quot;&gt;Speed&lt;/h2&gt;

&lt;p&gt;One of our current main issues in the Badoo Android team is our build speed (see more on that in &lt;a href=&quot;https://techblog.badoo.com/blog/2016/08/31/top-3-badoo-android-ama/&quot;&gt;our AMA follow-up blog post&lt;/a&gt;). Android instrumentation tests definitely do not help with it.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-08-16-how-to-convince-your-PM-into-refactoring-tests/androidtestbuildtime.png&quot; alt=&quot;Before&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The exact same test cases (8 to be exact) run in 22% of the time when done as a pure JUnit test. Most of this drop comes from the required instrumentation steps such as dexing, installing both the application and the instrumentation APK and bootstrapping them. This causes a significant overhead. It is true that this overhead does not grow too much with the number of test files and cases, but think about how many times you run just a handful test cases to ensure you don’t break something while modifying it.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-08-16-how-to-convince-your-PM-into-refactoring-tests/junittestbuildtime.png&quot; alt=&quot;After&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I agree that 25 seconds is still far away from perfect, but in our huge Badoo project that number is bliss!&lt;/p&gt;

&lt;h2 id=&quot;temptation-free&quot;&gt;Temptation free&lt;/h2&gt;

&lt;p&gt;Your unit tests must not interact with the Android framework. If you can’t mock it, then you have a design problem. But this same PM that you are trying to convince needs this new feature super quick, and oh the tests are failing, and it would be &lt;em&gt;so&lt;/em&gt; easy to just pass some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Context&lt;/code&gt; around… Nope, not today.&lt;/p&gt;

&lt;h2 id=&quot;its-not-that-difficult&quot;&gt;It’s not that difficult&lt;/h2&gt;

&lt;p&gt;Providing it is already a decoupled from Android framework test, it only takes you moving it from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/androidTest&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/test&lt;/code&gt; and adding a few &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@RunWith&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Test&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Before&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@BeforeClass&lt;/code&gt; annotations. How long would it take you, half a minute? Even if it took a couple of minutes, the second time you ran this test you would already have a benefit out of it.&lt;/p&gt;

&lt;h1 id=&quot;lets-do-the-math&quot;&gt;Let’s do the math&lt;/h1&gt;

&lt;p&gt;Until now, it’s all benefits for the dev team, but maybe your (PO|PM|PM) won’t see that just yet. Let’s add some numbers. Say you have 200 instrumentation tests. Out of those, 100 are easily converted to pure JUnit tests. Say they take 2 minutes to run, and let’s be conservative and say you save 50% of the time, that’s 1 minute.&lt;/p&gt;

&lt;p&gt;What value adds 1 minute? If the tests are ran 16 times a day (say once every half an hour in an ideal 8 hour work day), that’s 16 minutes per developer per day. 10 devs in your team, 2 week long sprints (thus 10 working days), it adds up to 1600 minutes or 26.6 hours. That’s more than 3 of those &lt;em&gt;developer days&lt;/em&gt; that (PO|PM|PM)s love so much to talk about. How about that!&lt;/p&gt;

&lt;h1 id=&quot;wrap-up&quot;&gt;Wrap up&lt;/h1&gt;

&lt;p&gt;There is no lost cause if there is data backing it up. Numbers don’t lie - although they can be presented in very suggestive ways…&lt;/p&gt;

&lt;p&gt;Of course, your mileage may vary, and in this example numbers are totally made up, but is not an unreasonable reasoning. next time you want to justify something to management, just tell them what they want to hear (backed up with actual data 😉)&lt;/p&gt;
</description>
        <pubDate>Tue, 16 Aug 2016 11:00:40 +0000</pubDate>
        <link>https://guillermoorellana.es/2016/08/16/how-to-convince-your-PM-into-refactoring-tests.html</link>
        <guid isPermaLink="true">https://guillermoorellana.es/2016/08/16/how-to-convince-your-PM-into-refactoring-tests.html</guid>
        
        <category>testing,android</category>
        
        
      </item>
    
      <item>
        <title>Integrating React Native in an existing application</title>
        <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Updated 11/04/2017:&lt;/em&gt; Added some of the API changes and updated the React Native version used in the article&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As I promised by the end of my previous article, &lt;a href=&quot;https://guillermoorellana.es/react-native/2016/06/12/writing-android-component-for-react-native.html&quot;&gt;“Writing an Android component for React Native”&lt;/a&gt;, here is the second approach for React Native and native Android code to live together &lt;del&gt;in peace and harmony&lt;/del&gt; and not blow apart. Since this is a follow-up to the previous article, I will jump straight into matter. If you need a brief introduction on React Native and how it’s organised on Android side, please visit the aforementioned link.&lt;/p&gt;

&lt;h1 id=&quot;getting-it-to-work&quot;&gt;Getting it to work&lt;/h1&gt;

&lt;p&gt;After &lt;a href=&quot;https://facebook.github.io/react-native/docs/embedded-app-android.html&quot;&gt;following the docs sample&lt;/a&gt;, you copy the snippets, run the commands… Et Voilá! Well… Not really. Actually the docs do not reflect the current state of the API, which is v0.42.3 when I ~wrote~ updated this paragraph. I will try to expose my issues and the ways I worked around them, but YMMV.&lt;/p&gt;

&lt;p&gt;An slightly updated version of the activity showing the React Native content would look like this:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ReactActivity&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AppCompatActivity&lt;/span&gt; 
    &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DefaultHardwareBackBtnHandler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ReactRootView&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mReactRootView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ReactInstanceManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LifecycleState&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mLifecycleState&lt;/span&gt; 
        &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LifecycleState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;BEFORE_RESUME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onCreate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@Nullable&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bundle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;savedInstanceState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onCreate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;savedInstanceState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;mReactRootView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ReactRootView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ReactInstanceManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setBundleAssetName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;index.android.bundle&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setJSMainModuleName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;index.android&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addPackage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MainReactPackage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setUseDeveloperSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;BuildConfig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setInitialLifecycleState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mLifecycleState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mReactRootView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;startReactApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; 
            &lt;span class=&quot;s&quot;&gt;&quot;ReactSample&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;setContentView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mReactRootView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onPause&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onPause&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;mLifecycleState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LifecycleState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;BEFORE_RESUME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onHostPause&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onResume&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onResume&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;mLifecycleState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LifecycleState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;RESUMED&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onHostResume&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onDestroy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onDestroy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;mReactRootView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;unmountReactApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;mReactRootView&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;destroy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onActivityResult&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requestCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resultCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; 
                                 &lt;span class=&quot;nc&quot;&gt;Intent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onActivityResult&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requestCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; 
                &lt;span class=&quot;n&quot;&gt;resultCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onBackPressed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;mReactInstanceManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onBackPressed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onBackPressed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;invokeDefaultOnBackPressed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;onBackPressed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The snippets for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index.android.js&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; seem fine for now at least 😎&lt;/p&gt;

&lt;p&gt;So you try to run it but…&lt;/p&gt;

&lt;h1 id=&quot;troubleshooting-time&quot;&gt;Troubleshooting time&lt;/h1&gt;

&lt;p&gt;These are the problems I found, but as always, YMMV.&lt;/p&gt;

&lt;h2 id=&quot;javalangunsatisfiedlinkerror-could-find-dso-to-load-libreactnativejniso&quot;&gt;java.lang.UnsatisfiedLinkError: could find DSO to load: libreactnativejni.so&lt;/h2&gt;

&lt;p&gt;Uh Oh! This sounds scary! What happened here? Well, I decided to test it on a Samsung Galaxy S7 (running Marshmallow, that also will be important in a second or two)… Which happens to be a 64 bit phone. And React Native &lt;a href=&quot;https://github.com/facebook/react-native/issues/2814&quot;&gt;does not provide a 64bit version of its binary&lt;/a&gt;. Usually Android would do a fallback, but this does not happen if you have a 64bit dependency in theory, but in practice I found it happening in a blank modern project.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/assets/article_images/2016-07-05-integrating-react-native-in-an-existing-application/linking-error.png&quot;&gt;&lt;img src=&quot;/assets/article_images/2016-07-05-integrating-react-native-in-an-existing-application/linking-error.png&quot; alt=&quot;Uh-oh&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;solution&quot;&gt;Solution&lt;/h3&gt;

&lt;p&gt;To avoid this, we will have to use some deprecated API in the gradle plugin in order to tell it to build exclusively for non-64-bit targets.&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;ndk&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;abiFilters&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;armeabi-v7a&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;x86&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Did I mention it’s a &lt;em&gt;deprecated&lt;/em&gt; API? Android Gradle Plugin will not like it. Just do as the warning says and add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;android.useDeprecatedNdk=true&lt;/code&gt; in your local &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gradle.properties&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-07-05-integrating-react-native-in-an-existing-application/deprecated.png&quot; alt=&quot;Ugh&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;better-solution&quot;&gt;Better solution&lt;/h3&gt;

&lt;p&gt;There is a better (and not deprecated) way of doing this:&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;packagingOptions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;exclude&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/lib/mips64/**'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;exclude&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/lib/arm64-v8a/**'&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;exclude&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/lib/x86_64/**'&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This way you ensure you get rid of the unsupported ABIs, instead of explicitly supporting a few.&lt;/p&gt;

&lt;p&gt;So you hit the “Run” button again and…&lt;/p&gt;

&lt;h2 id=&quot;badtokenexception-unable-to-add-window---permission-denied-for-this-window-type&quot;&gt;BadTokenException: Unable to add window  – permission denied for this window type&lt;/h2&gt;

&lt;p&gt;One very cool thing about developing in React Native is that you get to see the exceptions overlaid on top of your app if you are in debug mode.&lt;/p&gt;

&lt;p&gt;One very cool thing about Android Marshmallow is its new permission system, which allows you to take the power back and have a granular control on what you allow your app to do or not.&lt;/p&gt;

&lt;p&gt;One very &lt;strong&gt;not cool&lt;/strong&gt; thing about our empty app is that we do not request permission to draw over apps, but React Native will attempt to use it anyway, resulting on this beautiful stacktrace.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-07-05-integrating-react-native-in-an-existing-application/badtokenexception.png&quot; alt=&quot;Unexpected exception&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;solution-1&quot;&gt;Solution&lt;/h3&gt;

&lt;p&gt;A short snippet like this one, carefully placed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onCreate&lt;/code&gt;, will quickly ease your pain and show the app overlay permissions dialog instead of randomly crashing each time your app needs for it. You will still have to scroll through the whole list of apps that have that permission and manually enable our lovely React Native one by hand, but remember, this is only for debugging. Production apps do not require this permission.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;VERSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;SDK_INT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;VERSION_CODES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;M&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(!&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;canDrawOverlays&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Intent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;serviceIntent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Intent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;nc&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ACTION_MANAGE_OVERLAY_PERMISSION&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;startActivity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serviceIntent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;module-0-is-not-a-registered-callable-module&quot;&gt;Module 0 is not a registered callable module&lt;/h2&gt;

&lt;p&gt;This one was especially frustrating to get, since every piece of advice I could find was pointing out to an outdated React Native version. But that could not be! I was using the &lt;em&gt;highly discouraged by lint&lt;/em&gt; little + at the end of my Maven coordinates…&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;compile&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;com.facebook.react:react-native:+&quot;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// From node_modules&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So then I tried to change it to match the version I stated in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file, but hey, this is interesting!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-07-05-integrating-react-native-in-an-existing-application/mavenerror.png&quot; alt=&quot;Le what?!?&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Digging a bit deeper, found out that &lt;em&gt;the plus coordinates were pulling an outdated artefact from Maven Central&lt;/em&gt;. Digging even deeper, I found out my local Maven repo to be wrong.&lt;/p&gt;

&lt;h3 id=&quot;solution-2&quot;&gt;Solution&lt;/h3&gt;

&lt;p&gt;Change this&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;maven&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;$projectDir/node_modules/react-native/android&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To this&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;maven&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;$projectRoot/node_modules/react-native/android&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$projectDir&lt;/code&gt; is referencing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/&lt;/code&gt; subdirectory. D’oh! 🙈&lt;/p&gt;

&lt;p&gt;“This must be it” you naively think. But what happens if you try to open the debug menu?&lt;/p&gt;

&lt;h2 id=&quot;androidcontentactivitynotfoundexception&quot;&gt;android.content.ActivityNotFoundException&lt;/h2&gt;

&lt;p&gt;So, if you are debugging in a real device and not bundling the JS file, you can shake the phone in order to access the debug menu and…&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/assets/article_images/2016-07-05-integrating-react-native-in-an-existing-application/activitynotfound.png&quot;&gt;&lt;img src=&quot;/assets/article_images/2016-07-05-integrating-react-native-in-an-existing-application/activitynotfound.png&quot; alt=&quot;Thanks for the heads up, logcat&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seriously? AGH!&lt;/p&gt;

&lt;h3 id=&quot;solution-3&quot;&gt;Solution&lt;/h3&gt;

&lt;p&gt;Throw this into your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;application&amp;gt;&lt;/code&gt; tag, as our friendly exception suggests. Yep, as simple as that.&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;activity&lt;/span&gt; 
    &lt;span class=&quot;na&quot;&gt;android:name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;com.facebook.react.devsupport.DevSettingsActivity&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;result-and-conclusions&quot;&gt;Result and conclusions&lt;/h1&gt;

&lt;p&gt;After all these bumps and efforts, we finally got an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Activity&lt;/code&gt; to launch. Phew! What a long way! It was definitely not a bed of roses, and some issues did not appear to have an obvious fix after a quick Google search - but hey, maybe that’s just me being bad 🙈&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-07-05-integrating-react-native-in-an-existing-application/result.png&quot; alt=&quot;Hi! You took a long time to appear!&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And this is not the end of the road. You will still have to integrate the React Native toolchain into your build process (there is a nice Gradle plugin helping with that I believe) which adds complexity and build time.&lt;/p&gt;

&lt;p&gt;On the other hand, is a fair enough way of experimenting on an already existing application without taking the risks that a complete rewrite brings.&lt;/p&gt;

&lt;p&gt;But this was too simple, what about interactions between both sides? I guess I already have topic for the next React Native themed article… 🤔&lt;/p&gt;

&lt;p&gt;As always, &lt;a href=&quot;https://github.com/wiyarmir/React-Native-Android-integration-example&quot;&gt;code available in GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Tue, 05 Jul 2016 21:37:40 +0000</pubDate>
        <link>https://guillermoorellana.es/2016/07/05/integrating-react-native-in-an-existing-application.html</link>
        <guid isPermaLink="true">https://guillermoorellana.es/2016/07/05/integrating-react-native-in-an-existing-application.html</guid>
        
        <category>react-native,android</category>
        
        
      </item>
    
      <item>
        <title>Writing an Android component for React Native</title>
        <description>&lt;p&gt;&lt;strong&gt;(Updated 13/04/2017: Bumped to React Native 0.42.3 and updated code)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One of the cool things I like from working at Badoo (&lt;a href=&quot;https://corp.badoo.com/jobs/&quot;&gt;we are hiring!&lt;/a&gt;), is that we are free to propose, test and promote new or different techniques, technologies and libraries. React Native has been the buzzword for a while now, but it has recently gained our attention.&lt;/p&gt;

&lt;p&gt;Main concerns that came to our mind were the size of the existing codebase (let’s say, sizeable), our highly customised classes to fit our needs and easiness of integration. I decided to test the middle one, and try to write a custom Android component to use in React Native.&lt;/p&gt;

&lt;h1 id=&quot;react-native&quot;&gt;React Native&lt;/h1&gt;

&lt;p&gt;Probably almost everybody has already heard about React Native, but if you have not, &lt;strong&gt;TLDR:&lt;/strong&gt; it makes use of JavaScript and React but builds a native UI thanks to some clever bridge techniques.&lt;/p&gt;

&lt;p&gt;You can find all about it in the &lt;a href=&quot;http://facebook.github.io/react-native/&quot;&gt;project page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you generate a demo project by invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;react-native init&lt;/code&gt;, you will get a working skeleton, which is the one I will base the post on.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-06-12-writing-android-component-for-react-native/sample.png&quot; alt=&quot;Way prettier than your usual Hello World!&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Let’s attempt to extend it by adding a simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProgressBar&lt;/code&gt;. This is already implemented as part of the standard React Native distribution, but will serve us as an easy sample.&lt;/p&gt;

&lt;h1 id=&quot;android-side&quot;&gt;Android side&lt;/h1&gt;

&lt;p&gt;Extensions to the existing bindings are made by implementing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReactPackage&lt;/code&gt; class. It can be done in three different ways:&lt;/p&gt;

&lt;h3 id=&quot;1-native-modules&quot;&gt;1. Native Modules&lt;/h3&gt;
&lt;p&gt;They provide an inteface for JavaScript code to call native Java methods. For instance, exposing the Toast API as done in the documentation examples.&lt;/p&gt;

&lt;p&gt;C++ native modules are provided in a different way, so they can be fully cross-platform.&lt;/p&gt;

&lt;h3 id=&quot;2-javascript-modules&quot;&gt;2. JavaScript Modules&lt;/h3&gt;
&lt;p&gt;Basically the opposite way around: When you call on a method of a class implementing this interface, the equivalent will be called on the JavaScript realm.&lt;/p&gt;

&lt;h3 id=&quot;3-viewmanagers&quot;&gt;3. ViewManagers&lt;/h3&gt;
&lt;p&gt;Native views are provided through implementations of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ViewManager&lt;/code&gt; class, responsible of instantianting and updating views of a given type. This is the one we are interested in for now.&lt;/p&gt;

&lt;p&gt;Since we are only setting up a native view component, we will need to go from the ViewManager all the way up through several layers.&lt;/p&gt;

&lt;h2 id=&quot;the-viewmanager&quot;&gt;The ViewManager&lt;/h2&gt;
&lt;p&gt;All &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ViewManager&lt;/code&gt; instances need to report two things: a name to be mapped to a React class, and a way to create an instance of the view they manage. For our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProgressBar&lt;/code&gt; example, this is quite easy.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProgressBarViewManager&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleViewManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ProgressBar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;REACT_CLASS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;ProgressBar&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;REACT_CLASS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProgressBar&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createViewInstance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;nc&quot;&gt;ThemedReactContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reactContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ProgressBar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reactContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ThemedReactContext&lt;/code&gt; is just a wrapper on top of the Android &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Context&lt;/code&gt; we all know (and perhaps hate).&lt;/p&gt;

&lt;p&gt;With this done, React Native is able to instantiate a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProgressBar&lt;/code&gt; each time it finds the JSX tag for it.&lt;/p&gt;

&lt;h2 id=&quot;the-package&quot;&gt;The Package&lt;/h2&gt;

&lt;p&gt;At the package level, we do not need to return anything but our brand new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ViewManager&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ViewManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createViewManagers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;ReactApplicationContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reactContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Collections&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ViewManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;singletonList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ProgressBarViewManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The rest of methods can return empty collections safely for now, since we do not need anything from them.&lt;/p&gt;

&lt;h2 id=&quot;the-entrypoints-reactnativehost&quot;&gt;The entrypoints: ReactNativeHost&lt;/h2&gt;

&lt;p&gt;The boilerplate output of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;react-native init&lt;/code&gt; generates a subclass of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReactApplication&lt;/code&gt; (generally &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MainApplication&lt;/code&gt;). This wires the native Android calls down to the library. We need to add the new package to the list of packages reported to the JavaScript side, and we are more than done with Java world. This is done in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getReactNativeHost()&lt;/code&gt; method, but we usually declare a field for it:&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;ReactNativeHost&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mReactNativeHost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ReactNativeHost&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getUseDeveloperSupport&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BuildConfig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ReactPackage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getPackages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ReactPackage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;MainReactPackage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ProgressBarPackage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;javascript-react-side&quot;&gt;JavaScript (React) side&lt;/h1&gt;

&lt;p&gt;This step is quite simple, since most of it is handled by the React and React Native code. The only thing left for us to do is to describe the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;propTypes&lt;/code&gt; and export the module.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;use strict&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;nx&quot;&gt;NativeModules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;nx&quot;&gt;requireNativeComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;nx&quot;&gt;View&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;react-native&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;iface&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ProgressBar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;propTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;propTypes&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// include the default view properties&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ProgressBar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;requireNativeComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ProgressBar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;iface&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ProgressBar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You might be wondering what are those default view properties. Since we inherited &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SimpleViewManager&lt;/code&gt; (which extends &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BaseViewManager&lt;/code&gt;) when creating our own ViewManager, we can take advantage of that to have all the basic mappings from CSS to View properties solved for us. Those include properties such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opacity&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;backgroundColor&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flex&lt;/code&gt;. Full list available &lt;a href=&quot;https://facebook.github.io/react-native/docs/view.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What if we want to expose our own? Well…&lt;/p&gt;

&lt;h1 id=&quot;exposing-view-properties&quot;&gt;Exposing view properties&lt;/h1&gt;

&lt;p&gt;In the Java side, we need to create our setters in the ViewManager implementation and annotate them with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ReactProp&lt;/code&gt;. There we note the name of the property coming from JSX world, and optionally we can define a default value.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@ReactProp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;progress&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defaultInt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setProgress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ProgressBar&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;progress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setProgress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;progress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@ReactProp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;indeterminate&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;defaultBoolean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setIndeterminate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ProgressBar&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                             &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indeterminate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setIndeterminate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indeterminate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This setter will be called every time the property of our React component is updated. In case of the property being removed, then the default value is used.&lt;/p&gt;

&lt;p&gt;Then, we need to add it to the React Native interface. Back in the js file, at our module’s iface we should describe the properties we exposed in the ViewManager, both with name and type.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;iface&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;propTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;progress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PropTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;indeterminate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PropTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This way, both native and React sides will speak in the same terms. In the end, our module’s JS file would look something like this:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;use strict&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PropTypes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; 
  &lt;span class=&quot;nx&quot;&gt;NativeModules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;nx&quot;&gt;requireNativeComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;nx&quot;&gt;View&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;react-native&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;iface&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ProgressBar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;propTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;progress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PropTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;indeterminate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PropTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;propTypes&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// include the default view properties&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ProgressBar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;requireNativeComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;ProgressBar&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;iface&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ProgressBar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;all-together&quot;&gt;All together&lt;/h1&gt;

&lt;p&gt;Kickstart the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;react-native&lt;/code&gt; server, deploy the APK to your favourite emulator or real device, and if nothing is missing the million gear machine will produce something that looks more or less like this.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://media.giphy.com/media/3og0IGbeL7kOBVfebC/giphy.gif&quot; alt=&quot;They see me rolling...&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;aftermath&quot;&gt;Aftermath&lt;/h1&gt;

&lt;p&gt;React Native, more than a year after its public release (and not even one after the Android release), is in a way more mature state than the last time I attempted anything on it. You can have a working boilerplate project with one command. Docs are very helpful and community content is great.&lt;/p&gt;

&lt;p&gt;However, it still feels very cumbersome to integrate it with complex modules.&lt;/p&gt;

&lt;p&gt;There is, nevertheless, an alternative approach. Instead of having a brand new React Native application adopt native components, there is the possibility of doing the complete opposite - having a mature production application integrate one simple React Native component.&lt;/p&gt;

&lt;p&gt;From reading the docs, it looks more complicated than it sounds, and I have some concerns about the build process - speed and reliability. But that’s food for another thought, and most likely another post. Stay tuned!&lt;/p&gt;

&lt;h1 id=&quot;links&quot;&gt;Links&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/wiyarmir/React-Native-Android-component-example&quot;&gt;GitHub repo with the final code&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Sun, 12 Jun 2016 15:37:40 +0000</pubDate>
        <link>https://guillermoorellana.es/2016/06/12/writing-android-component-for-react-native.html</link>
        <guid isPermaLink="true">https://guillermoorellana.es/2016/06/12/writing-android-component-for-react-native.html</guid>
        
        <category>react-native,android</category>
        
        
      </item>
    
      <item>
        <title>#YAGIOR - Yet Another Google I/O Recap</title>
        <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; It was my first time in Google I/O, my first time in the Bay Area, my first time in California, my first time in the US… And I came back with a very different opinion on all of them.&lt;/p&gt;

&lt;h1 id=&quot;the-long-version&quot;&gt;The long version&lt;/h1&gt;
&lt;p&gt;I am writing a very late recap. I could blame it to the fact that I am lazy and Spanish, but the ones who know me well would point out that’s not usually an obstacle for my punctuality. It is a late one, because I have had experienced many things and have had a lot to assimilate. But let’s do it one part at the time, shall we?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-06-01-yagior-yet-another-googleio-recap/gbikes.jpg&quot; alt=&quot;Colourful bikes&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;google-io-the-conference-festival&quot;&gt;Google I/O: The &lt;del&gt;conference&lt;/del&gt; festival&lt;/h1&gt;
&lt;p&gt;Yes. The festival. If it looks like a festival, smells like a festival, tastes like a festival, you get sunburnt like in a festival… It is a festival, isn’t it? &lt;em&gt;FestivalTyping™&lt;/em&gt; at its finest!&lt;/p&gt;

&lt;p&gt;It was hard to get into the sessions. Places were limited, so you had to queue. People queueing were kissed by a quite strong californian sun. So people got sunburnt. And angry, but mostly sunburnt.&lt;/p&gt;

&lt;p&gt;Don’t get me wrong, I &lt;strong&gt;loved&lt;/strong&gt; the concept. I also do not think Google was unprepared or careless about it. They could have transmitted the message a bit better, provided a bit more of shade… &lt;em&gt;But it was very clear it was going to be a festival.&lt;/em&gt; And festivals are &lt;strong&gt;hard&lt;/strong&gt; to manage. Not NP-hard, but sure it’s right about there.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-06-01-yagior-yet-another-googleio-recap/keynote.jpg&quot; alt=&quot;Roasted Geeks&quot; /&gt;&lt;/p&gt;

&lt;p&gt;On the other hand, my opinion is that the last things that matter in a big event such as Google I/O are the actual sessions. It’s 2016 people. Most of the sessions are live-streamed, and all of them are available on demand 24 hours after. So if you want to attend just to listen to it, well… It is not a concert, you will not find the difference between attending in person or through  YouTube in the comfort of your sofa - wait, maybe you &lt;em&gt;will&lt;/em&gt; find it different.&lt;/p&gt;

&lt;p&gt;The important bits are &lt;strong&gt;the people&lt;/strong&gt; you meet there. I met fellow developers from all over the world (and a lot based in London I did not happen to have met yet!), writers from the tech media I consume daily. But the most valuable opportunity for me, was to meet the googlers that make the tools I use on a daily basis as part of my job. I was able to express my frustrations, doubts and  problems. And some of them happened to be important enough!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-06-01-yagior-yet-another-googleio-recap/amphitheatre.jpg&quot; alt=&quot;Not your usual conference venue™&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Coming back to the unhappy people, my overall impression was that they were so used to in-building conferences and perhaps not too familiar with the place and the way the sessions were run, that they underestimated the sun of the Bay Area. Which brings me to…&lt;/p&gt;

&lt;h1 id=&quot;the-bay-area&quot;&gt;The Bay Area&lt;/h1&gt;
&lt;p&gt;The whole area is crazy. From the window of my ride to the conference, I did not stop counting big names: Electronic Arts, Oracle, Tesla, Motorola… Every single one of them. Of course I knew it already, but still impacted me being there. Oh, and of course Google. But I have talked already enough about them.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-06-01-yagior-yet-another-googleio-recap/twinpeaks.jpg&quot; alt=&quot;Stitched view from Twin Peaks. The real one, not the TV fiction one.&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;california&quot;&gt;California&lt;/h1&gt;
&lt;p&gt;I did not have much free time out of the conference, so no fancy road trip to LA - I will leave that for the next visit. However, from the small sample I had from San Francisco to San Jose, I did notice a couple of things.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;I missed that sustained amount of sun - even if I ended up getting sunburnt.&lt;/li&gt;
  &lt;li&gt;People are much nicer than in London.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every american I talked about this with mentioned that I might have been a bit spoiled, since other states are not as nice apparently. That does not keep me from wanting to visit them all!&lt;/p&gt;

&lt;p&gt;And don’t get me wrong, people in London are not &lt;em&gt;mean&lt;/em&gt; in general, but they are &lt;em&gt;not as&lt;/em&gt; warm and open, by a long shot.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-06-01-yagior-yet-another-googleio-recap/alcatraz.jpg&quot; alt=&quot;Zoomed in Alcatraz view from the docks&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;the-united-states&quot;&gt;The United States&lt;/h1&gt;
&lt;p&gt;Thanks to countless TV Series and movies, in Europe we have a strong stereotype of what you might find on your arrival to the US.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Awkward wedding proposal taking the mic from the band? Check.&lt;/li&gt;
  &lt;li&gt;Shitty public transportation? Check.&lt;/li&gt;
  &lt;li&gt;Twin Peaks? Check.&lt;/li&gt;
  &lt;li&gt;Crazy ass shopping malls? Check.&lt;/li&gt;
  &lt;li&gt;In-n-out burger? Check.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/assets/article_images/2016-06-01-yagior-yet-another-googleio-recap/innout.jpg&quot; alt=&quot;Feels like in a Tarantino movie...&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;/h1&gt;
&lt;p&gt;I have had way too many first time experiences on this one in order to make a comparison or thoughtful evaluation. I am very happy that I had the opportunity to join this year’s Google I/O and I am looking forward to the next one!&lt;/p&gt;

&lt;p&gt;Keep tuned for follow up posts for some of the things I have learned and discovered during my time in California.&lt;/p&gt;
</description>
        <pubDate>Thu, 02 Jun 2016 22:38:06 +0000</pubDate>
        <link>https://guillermoorellana.es/2016/06/02/yet-another-google-io-recap.html</link>
        <guid isPermaLink="true">https://guillermoorellana.es/2016/06/02/yet-another-google-io-recap.html</guid>
        
        <category>google</category>
        
        
      </item>
    
      <item>
        <title>Testing Android's AlarmManager</title>
        <description>&lt;p&gt;When I joined Coniq, I had to maintain and extend an existing Android application, which I did not really understand deep enough to feel safe to make big changes that it needed. So I decided to put some scaffolding around in shape of tests, in case everything decided to fall down. One of the parts I found most difficult to deal with, was Android’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AlarmManager&lt;/code&gt; related code.&lt;/p&gt;

&lt;h1 id=&quot;what-is-alarmmanager&quot;&gt;What is AlarmManager?&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AlarmManager&lt;/code&gt; is an old friend. It has been available in the Android API literally forever, starting Android 1.0 (API Level 1)&lt;/p&gt;

&lt;p&gt;It is very useful when you want to schedule a task in the future and do not want to involve nasty Handlers or native Threads which can make your code practicably untestable together with many other concerns.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AlarmManager&lt;/code&gt; is a system service, thus you need a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Context&lt;/code&gt; to instantiate it from.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;AlarmManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alarmManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AlarmManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSystemService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ALARM_SERVICE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;how-to-use-alarms-in-android&quot;&gt;How to use alarms in Android?&lt;/h1&gt;

&lt;p&gt;Simple! You create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PendingIntent&lt;/code&gt; for your favourite service, activity or broadcast and pass it to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AlarmManager&lt;/code&gt; instance through the appropriate method. In this example I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setInexactRepeating&lt;/code&gt; but you can use whichever you find suitable. Full list as always &lt;a href=&quot;http://developer.android.com/reference/android/app/AlarmManager.html#pubmethods&quot;&gt;in the docs&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alarmMgr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setInexactRepeating&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;AlarmManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ELAPSED_REALTIME_WAKEUP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// type: wake if device asleep&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;SystemClock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;elapsedRealtime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// first repetition: asap!&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;AlarmManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;INTERVAL_HALF_HOUR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// consequent repetitions: every half hour&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;alarmIntent&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// PendingIntent to launch on alarm&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that’s it! The Android system will call your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PendingIntent&lt;/code&gt; once the timeout has been met. Bear in mind that for &lt;strong&gt;apps targeting API 19 and higher alarms are no longer exact&lt;/strong&gt;, and they can (and will) be deferred under OS discretion with the purpose of saving battery. This is, if your application is compiled against KitKat or higher, you cannot rely on the accuracy of any method which is not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setWindow&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setExact&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;how-to-test-alarms-in-android&quot;&gt;How to test alarms in Android?&lt;/h1&gt;

&lt;p&gt;Such a nice system functionality. You create the alarm, set it up and forget about it. Err but… How to &lt;em&gt;test&lt;/em&gt; it?&lt;/p&gt;

&lt;p&gt;Nowadays Robolectric is a de-facto standard in Android unit testing. However, for AlarmManager I decided to make my tests instrumentation tests, since it is a functionality that relies heavily on Android System features. I might rewrite it for Robolectric when 3.1 is out.&lt;/p&gt;

&lt;h2 id=&quot;how-to-check-if-an-alarm-is-set&quot;&gt;How to check if an alarm is set?&lt;/h2&gt;

&lt;p&gt;The only access to system alarms in Android is some nasty adb command that dumps the whole system status. That does not sound right, does it? But don’t panic. As &lt;a href=&quot;http://stackoverflow.com/questions/4556670/how-to-check-if-alarmmanager-already-has-an-alarm-set&quot;&gt;this StackOverflow question&lt;/a&gt; points out, there is a clever way of checking for your pending intents.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isAlarmSet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Intent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;intent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyAlarmReceiver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTargetIntent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;PendingIntent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PendingIntent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;intent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;nc&quot;&gt;PendingIntent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;FLAG_NO_CREATE&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note the flag, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PendingIntent.FLAG_NO_CREATE&lt;/code&gt;. As per &lt;a href=&quot;&quot;&gt;documentation&lt;/a&gt;, this flag will make the method call return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PendingIntent&lt;/code&gt; is not found in the system. This way we can check for our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PendingIntent&lt;/code&gt; in the system, and thus our alarm.&lt;/p&gt;

&lt;p&gt;In order for this to work, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Intent&lt;/code&gt; used in the call must pass the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Intent.filterEquals()&lt;/code&gt; test. This is, must have same action, data, type, class and categories. Any extra data is ignored. Additionally, you need to call the same getter, e.g. if you created it calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getService&lt;/code&gt;, you must use it for
the check as well.&lt;/p&gt;

&lt;h2 id=&quot;what-could-i-test&quot;&gt;What could I test?&lt;/h2&gt;

&lt;p&gt;Well, you will want to test that your alarm is actually set when you want it to be.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testSetAlarm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;MyAlarmReceiver&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyAlarmReceiver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setAlarm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isAlarmSet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That is not set &lt;em&gt;automagically&lt;/em&gt;…&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testCancelAlarm_notSet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;MyAlarmReceiver&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyAlarmReceiver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isAlarmSet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isFalse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that you are able to unset it!&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testCancelAlarm_set&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;MyAlarmReceiver&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyAlarmReceiver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setAlarm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isAlarmSet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;cancelAlarm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isAlarmSet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isFalse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;help-all-my-cancel-related-tests-are-red&quot;&gt;Help! All my cancel-related tests are red!&lt;/h2&gt;

&lt;p&gt;Be careful here. For these tests to work, you have to cancel &lt;strong&gt;both&lt;/strong&gt; the alarm and the pending intent.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;cancelAlarm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Context&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;[...]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alarmMgr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;alarmMgr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;cancel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alarmIntent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;getPendingIntent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;cancel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;[...]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;clean-up-before-you-leave&quot;&gt;Clean up before you leave!&lt;/h2&gt;

&lt;p&gt;Have you ever heard of the &lt;a href=&quot;http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule&quot;&gt;Boy Scouts’ rule&lt;/a&gt;? Well, in tests it is quite important to clean up your mess!&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@After&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tearDown&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAlarmManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAlarmManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;cancel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;receiver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAlarmIntent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make sure you cancel any alarm that might have not been cancelled already by the end of the test. Uncle Bob would be proud!&lt;/p&gt;

&lt;h1 id=&quot;further-testing&quot;&gt;Further testing&lt;/h1&gt;

&lt;p&gt;That should be it for alarm setting and cancelling. But there are many many more things we can test! For instance, enforcing that we only set up one alarm at the time, that the alarm gets the right pending intent or what happens when the pending intent is invalidated before alarm goes off.&lt;/p&gt;
</description>
        <pubDate>Thu, 24 Sep 2015 10:41:06 +0000</pubDate>
        <link>https://guillermoorellana.es/2015/09/24/testing-android-alarmmanager.html</link>
        <guid isPermaLink="true">https://guillermoorellana.es/2015/09/24/testing-android-alarmmanager.html</guid>
        
        <category>android</category>
        
        
      </item>
    
  </channel>
</rss>
