Diving into React Native on Cloud Devices

I’ve heard that React Native is really cool. I’ve heard it can help to change your delivery, team, and hiring strategy. I’ve also heard it’s toolchain is immature and that it’s not ‘enterprise friendly’.

Extraordinary claims require extraordinary proof, so I decided to put it through the paces I see enterprises require every day. Namely, how do you use a cloud lab in situations where you’re debugging a critical incident found in production?

Since I have a variety of real mobile devices at my disposal in the Perfecto cloud, let’s see how quick it is to connect React Native to one of them!

Side question: what was the last physical mobile device you needed to debug an issue on a specific platform, carrier, or form factor?
Click here to tweet me your answer!

Running React Native Code on a Real Device

Sitting in the back row of a local meetup, I quickly installed the requisites on my MacBook, launched a Perfecto device, and was up and running. Like all bootstrap activities, this was flawless. Then I ran the usual ‘react-native run-android’:

First snag, unlike Android Studio, the magic dust that ships with React to automate the Gradle build and deploy process was lacking the -s command, which of course failed the build process. The maturity of React tooling is a side-topic, but all we need is to amend that parameter with a device serial number.

Listing the devices, we see that my cloud device correctly registers in ADB:

After copying the ADB command and rerunning with the -s argument added, the app ran, but with some debugging connectivity issues.

Debugging React Native on a Different Network

What this message is telling us is that stunnel is configured to allow our computer to see the device, but not the other way around.

Since React Native debugging needs to load javascript hosted by your workstation, we’ll need to point debugging on the device to an address that resolves to your workstation’s address. I use ngrok for this.

./ngrok http 8081

This produces a dynamic hostname that will forward all incoming traffic on port 8081 down to my local workstation where the React server is running.

To get to the React Native developer tools on the device to have the right debugging server address, I simulate a device shake by sending a keypress 82 command, then navigate to ‘Dev settings’ and ‘Debug server host & port…’:


And voila! A React Native app on a real Samsung Galaxy S7 device hosted in the Perfecto cloud running in debug mode!

Could this be easier? Sure, if React Debugging used ADB to do all debugging interactions, but that would mean a lot of re-architecting on their part. The simple fact is, React Native debugging dictates access to the developer workstation via HTTP, so ngrok is kind of necessary due to their tooling.

Next steps:

You could automate the IP configuration in AppDelegate.m like this walkthrough does if you want to.

You could probably even grep the dynamic host name in a shell command and write it dynamically to that file before React Native deployment to the device. But that would be another article.

More reading:

Beyond the Boston Women’s March for America

My brave, introverted wife marched yesterday in Boston while I took the kids to the park and cleaned up the house. It’s the least we both could do.

After a political turnover that can only be compared to falling down a rabbit hole and ending up back in the 50s in a communist Russia run by a crotchety, ignorant oompa loopa, this is what America has come to. Some of our most intelligent, kind, and confident people having to protest for freedom, upholding basic human rights, and against bigotry.

America: So Bad, Even Introverts Rally

I am my wife’s husband. We are very different. The way she recharges is to stay in doors and knit something. I like to stay out late and meet new people. But that’s what she did yesterday. She went with an extroverted friend and surrounded herself with 110,000 other people because involvement matters. She hugged a college student and they both started crying together in public.

That’s why she’s brave in my book, because in her book these kinds of extroverted things don’t happen, but they do when it matters.

Since I wasn’t there, I didn’t get to see city residents supporting the cause from their windows stories above the march. All my worst fears after the Boston marathon bombing were unnecessary because there was not a single reported negative incident. Service vehicles that blocked off the streets from traffic honked their horns in solidarity as people proudly walked by…that’s what my wife came back with, a story of hope and meaning.

After over a year of thinking about what lead up to this, I would like to offer a few thoughts, and one big suggestion.

Leaders who actually lead deserve our attention

Most of our current representative government is awful. They’re just awful. Both sides, but what I really mean by ‘most sides’ is most of the majority side.

What other options to we have? Let’s recap.

Elisabeth Warren takes to task any politician who practices corruption, champions education and equality, or supports the subjugation of others. Why the fuck isn’t she our president already? The short answer is that for all her rights, America is still so sexist (even women) and she’s so left that it would be hard to expect a majority of voters not to mention our current political complex to accept her…

…but oh wait, Washington just elected the Actual Antichrist (if you believe in that sort of hoo haw), so I guess it’s entirely possible to get a left-wing presidential candidate who is overqualified and underrepresented elected in 2020. Let’s focus our party efforts to do just that.

Or how about Bernie Sanders, the candidate that we the people never got the chance to vote for. During protests across the world yesterday against This Desolation Presidency, our Bern spoke out for human rights in his home state.

Are you kidding me? I actually feel a little mentally disabled when I think about how this guy lost in a race against Fat-Fingers McGrabspussy. Are we blind, deaf, dumb, stupid, or all of the above for not giving him an oval room to run the free world?

If a majority of white America can’t yet accept that a women should truly be leading us as a global power at this point, then Sanders was the most obvious and amenable solution to our current State of Bias.

Accept and move beyond our mistakes

We can’t ignore our mistakes without being doomed to make them again.

The Democratic party gambled on a risky political figurehead and lost BIG. There was enough time and examples of Russian-colluding rhetoric before the primaries to expect that the presidential race would be fought dirty, and picking a candidate carrying so many possible vectors of attack was a poor choice no matter how progressive or technically qualified they were.

DNC leadership failed not only its constituents, but all of America by driving the Republican party to put up such poor choice traditional candidates such as Ted Cruz and Ben Carson that conservative voters would rather side with a small-minded (and small-handed) demagogue than ever consider voting for the other side.

We have to fix that now, there is no good 2020 outcome without a reboot.

Fight propaganda with informational literacy

Disinformation also needs to be a solved problem by next time around. I’m not talking about simply plugging our security gaps, I’m talking about educating people on how to filter opinion from fact. The battle is fought one person (not article) at a time.

Informational literacy enables people to form their own ability to think rationally and critically about what’s being presented to them. Everyone is biased, and everyone deserves to work their own flaws out; but being able to agree upon basic facts starts by teaching people (especially those still in formative stages) how to distinguish and agree upon facts.

Listening is also a mandate next time around. Confusion and intolerance about a bad idea is fine, but let that go to far and it blinds you to what may actually be going on. Free speech applies to idiots, villains, thieves, and zealots too, sadly. Clearly, I’m okay with name-calling and sometimes irrational arguments. but keep in mind that shutting people out of communicating their bad ideas doesn’t kill the bad idea; it just incubates it.

A Solution for Next Time Around: Inclusion Beyond Under-representation

So let’s do this. Let’s adjust the strategy to include, not exclude, both our hopes and our reality. Let’s continue to fight for human rights, stand up for others who don’t have the same level of privilege as us, and remember that even people with bad ideas are people who vote.

We can and will hijack enough mindshare in the next four years to vote based on better ideas, but it will take patience, tolerance, and perseverance. Who knows, maybe we’ll learn something about how to change people instead of just saying that we can. That’s a party I’ll belong to.

More Reading:

Locale bugs & currency formatting in Android Studio

I grew up in the United States and like most countries I’ve traveled to, I’m used to seeing money that look like this:   $56.33   €12,50   £281.71

A modern IDE tells you when you’re ignorant

Today, Android Studio was kind enough to tell me that some sample code had a problem: “Implicitly using the default locale is a common source of bugs”. Nice.

Looking at this sample code, I asked myself: “Why should the UI format this number, isn’t that going to hide what the underlying application logic is saying?”

So it was a great thing that Android Studio shows little messages like this because it got me thinking about how to properly handle currency in the view layer.

Simply changing your app code won’t save you!

This is a case where view layer formatting isn’t the appropriate place to deal with rounding. The business logic of this application, the algorithm that calculates tips, should ultimately be in charge of rounding to the locale-appropriate currency decimal place, in Java this means using the BigDecimal class for manipulating values. So, I forked my own copy and updated the sample to remove the view formatting code.

Then I changed the locale on my device, and my Espresso tests started breaking.

See, when you write your format codes and test logic under a narrow mindset of one locale/language/currency (en_US), the test data you use can break your tests if the app is run under a different locale (ar-IQ) which format things like currencies (USD, IQD) to a different arithmetic precision (the dollar uses 2 decimal places, the Dinar uses 3). [locale/currency lookup table]

An example of an Espresso test written assuming western currencies can be found below. Dinar has three decimal places, so this particular sample fails because values are handled as doubles (floating point numbers). Without controller logic to deal with rounding, it comes out as 35.912 which is not the same as the 2-decimal data “35.91” in my test code.

To simplify things, much of the code is written using doubles to pass currency around, even though this isn’t best practice. Even still, so long as we use BigDecimal to handle the higher-order calculations, we can downgrade the decimal precision in outbound double values to the view layer. Then we have the option of using locale-accurate test data, managing the precision in our tests as well.

Check it out for yourself…

If you want to spin these examples up yourself, you can clone my repo. Also, if you want to see this work in continuous integration, check out my article on running a Jenkins / Android build server on Docker.


Jenkins on Docker to build Android apps

For an reference example, I had to set up Jenkins to build my Android app. Though I’m using a Mac, once Docker is involved, I can also use the exact same steps on my Windows machine too, and so can you.

  1. Install Docker
  2. Use my existing Docker setup files
    1. Grab the contents of this GitHub folder to your machine
    2. Change directory to where you saved the above contents
    3. Build the docker files to create images. Run: 

    4. Run these freshly minted Docker images as a new container:


  3. In a browser, log in to your Jenkins instance at
  4. Complete the initial Jenkins setup by walking through the on-screen prompts

Much thanks to Sha who wrote this article that quickly highlights the steps for getting Jenkins 2.0 running on Docker. All I added to my Dockerfile was steps to install the Android SDK so that Jenkins can build my app.

Related reading:


Installing Android SDK in Docker

For a recent project, I had to include the Android SDK build tools as part of a Jenkins Dockerfile. No problem. Download and execute installer, right?

Wrong. With Google installers come license agreements, and I needed a way to reliably accept the terms and conditions of the installer and it’s dependencies automatically. Here’s what my Dockerfile looks like:

Not complicated, really, but worth documenting for others out there.

Backwards-compatibility for Build Tools in Jenkins

I have ‘build-tools-24.0.1’ in there because the app I’m working with has not been upgraded to the latest version of Gradle, but it’s worth noting too because not everyone has the luxury of changing code/compile settings just because Google ships new binaries. Thanks Google, you really know how to break my build. ;*

Instead, I chose to own the responsibility of the version of tools needed on my build nodes for the types of projects I intend to compile on them. Because of this, I need to know the specific android update sdk filter codes that correspond to the pretty package names I see on my workstation in SDK Manager.

To list the codes that you might need in your own update filter, use the following command under your Android SDK tools folder:

…which displays a list like this:

That is all.

Semi-related Reading: