Using translations on both Flutter and native Android

Hi @here!

The latest project I’m working on is a Flutter app that works as a phone app. I mean an actual phone app. An app intended to make and receive phone calls. Supporting that requires a lot of platform code aka native Android code. That being said, now let’s share the problem: we need to manage translations on Flutter for UI, and on Android for native system notifications. A mess is incoming!

The first thought I had was to send the translations I had on Flutter to the platform via MethodChannel, and then save them on the native platform side, and use them in the native components. It was complex. So I would say don’t do that.

The second attempt and I think the best one, came to my mind when integrating the actual translations platform, in the case of this app, PhraseApp. As most translation platforms, they have an API that you can use to download the translations flawlessly, from the command line. Why is that idea so great that it deserves a post on the blog?

I download the translations in both ARB for Flutter and XML for Android. So, I have the translations ready to use from both sides of the project without the hassle of any synchronization. They are there ready to go!

If you don’t use PhraseApp (as I do in many projects), you will have to do it by yourself. But if you are lucky enough to use PhraseApp, I think you will be delighted with this .phrase.yml.

Feel free to be inspired by it!

Some hacky things to know about the Kindle Paperwhite

Hi everyone!

Here’s one more note for myself and for everyone. I can’t forget anything of these not-that-easy things about the Paperwhite e-reader.

If you want to disable the screensaver, tap the search box and type in ~ds, the acronym for don’t sleep. I guess. Or disable screensaver? Who knows… but hey, they’re good hints, aren’t they?

To change the timezone of the device, in case you need the Javascript of the Experimental Browser to successfully convert timestamps to Date, you have to setup the timezone in your Wi-Fi router. That’s mad!

This is how the timezone selection looks in my router
This is how the timezone selection looks like in my router

If you are wondering why I needed that, it’s just to convert the Kindle reader in a weather station. Feel free to check my mad repo on GitHub to know more. And happy hacking!

Install Tomcat 8.5 on Debian 9 with Java 8

Hey folks! Do you remember the hard ages when you have to install Java and Tomcat by hand when setting up a new Debian server? Now, I tried setting up a Tomcat 8.5 server just using apt-get commands, and it works! So, here’s the list of commands that you and me in the future have to run when setting up a new Debian 9 + Java 8 + Tomcat 8.5 server.

su
apt-get update &&
apt-get -y upgrade &&
apt-get -y install ntp cron htop tomcat8 tomcat8-admin

Then, just change the content of the Tomcat users file:

vim /etc/tomcat8/tomcat-users.xml

And append this content:

<role rolename="admin-gui"/>
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<user username="YOURUSER" password="YOURPASSWORD" roles="admin-gui,manager-gui,manager-script"/>

Restart Tomcat… et voilá!

/etc/init.d/tomcat8 restart

Nice! Our environment is ready for production. But… just until the disk becomes full of logs. So, let’s clean the Tomcat logs daily. As we installed cron previously, we can create a script under /etc/cron.daily to remove those huge log files.

vim /etc/cron.daily/fewlaps-disk-cleaner

#!/bin/sh
rm -rf /var/log/tomcat8/*

Note that the last * mark is important. If we delete the whole directory instead of the contained files, Tomcat will not start anymore. That’s not exactly production-ready. Finally, give execution permissions to that script.

chmod +x /etc/cron.daily/fewlaps-disk-cleaner

Nice! Now, in case you want to monitor this brand new Tomcat via JMX, you’ll need to enable JMX. Internet is full of answers, but this one will be specific for Tomcat 8.5 on Debian 9. Everyone will have Tomcat installed in the same place, so let’s make something copypasteable. The thing is to create a new file setenv.sh with a new line that sets CATALINA_OPTS, and two files to authenticate a user to monitor the instance and another one to control it.

vim /usr/share/tomcat8/bin/setenv.sh

CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=8042 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.access.file=/usr/share/tomcat8/jmxremote.access -Dcom.sun.management.jmxremote.password.file=/usr/share/tomcat8/jmxremote.password"

vim /usr/share/tomcat8/jmxremote.access

readonlyusername   readonly
controlusername    readwrite \
              create javax.management.monitor.*,javax.management.timer.* \
              unregister

vim /usr/share/tomcat8/jmxremote.password

readonlyusername  READONLYPASSWORD
controlusername   WRITEPASSWORD

chown tomcat8:tomcat8 /usr/share/tomcat8/jmxremote.*
chmod 400 /usr/share/tomcat8/jmxremote.*

And that’s all! I will update this post if I detect something to improve. Guys behind Debian 9: THANKS! You made my life easier.

Introducing EDD

Do you know EDD? EDD means Error Driven Development, aka “Write a test to reproduce the bug before fixing it”. That sentence leads the InfoJobs’ app to the zero bugs dream. And here are some slides to help me spread the idea to Schibsted’ teams:

What I feel when opening a Presenter class for first time

In this list of public methods, which ones are just handling the View’s events?

When you open a new Presenter that has several methods, it’s a pity to see a lot of methods. You feel overwhelmed of don’t know the flow of the screen. What methods are handling a View’s event? What methods are really doing Presenter business?

Please please please, when writing a Presenter, just call the methods that receive events onSomething(). Instead of login(), onLoginButtonClicked(). That way leads to easy knowing what are the View events that this Presenter has to manage. And, the best of it, when following this rule, it’s easier to write tests. In your tests, you should just call onSomething() events and verify that some View methods are called with the expected values.

And remember: the View has to be dumb. Just forwarding View events to the Presenter, and just offering methods to the Presenter to do View things. The Presenter is the responsible of actually doing the business of that screen, so the View has to be responsible of doing what the Presenter expects from it.

Ideas about Android engineering

I need a place to put some ideas about developing Android apps in a clean way.

As we want to test our domain in a quick and simple way, we need to write code testable with just the JUnit framework. We need to avoid using Roboelectric, PowerMock and that kind of frameworks, as they are not simpler than just avoiding them :·)

How to do that? Just try to avoid depending on Android things, like the Context, SharedPreferences, SQLite classes…

… and that’s all! Just a small post launched to the world!

Let’s talk about commit messages

… or look at this great Chris Beams post: http://chris.beams.io/posts/git-commit/

Everything started ’cause I requested a colleage about stop ending the messages with a period. And then, I realised that my messages starting with “adding”, “fixing” and other continous pasts doesn’t has any sense. So, I started writing in imperative.

Thanks Chris :·)