Self-Signed Certificates with OkHttp – the Right Way

Your sysadmin comes to you and says “hey, let’s quit using the developmestruction environment, I set up this new test server we can test with instead.” Awesome.  This is definitely a good thing for your development.

So you switch the URL your app is calling, but now you’re getting see this:

Screen Shot 2016-06-05 at 7.02.02 PM

Why can’t you connect?  Well, SSL certs cost time and money, so a lot of times in internal test and development environments you’ll see self-signed certificates.  By default, OkHttp isn’t going to trust those, since they aren’t signed by a known, trusted Certificate Authority (CA).

At this point, you may find some StackOverflow answers suggesting that you make a dummy TrustManager that just blindly accepts any SSL certificate.  Don’t do that.  You may as well disable SSL at that point, because anybody can run a man-in-the-middle attack to read and/or manipulate your traffic.  Seriously, just don’t.  Even for your test environment.  

The good news is, it’s just as easy to fix the right way by adding trust for your self-signed certificate.  Here’s all it takes:

Step 1: Download the .cer file

1-chrome-broken-lock

Open the URL in Chrome.  You’ll see the broken lock icon in the address bar; click it. Your goal is to drag the certificate to somplace you can work with it; Chrome will give you a .cer file.  (screenshots are small, click to embiggen)

1b-chrome-not-private1c-connection-detail

1d-cert

Step 2: convert to .pem, using this in your terminal (and maybe spend a minute with “man openssl” to see what’s up here – we’re converting from one certificate file format to another)

openssl x509 -in server.cer -inform DER -out server.pem -outform PEM

Step 3: Drop the .pem in your app’s assets folder

Step 4a: Here’s how to add that custom cert to OkHttp3

Step 4b: OkHttp2 version

Run it again, and you’re good to go.

Android dev tip: Custom fonts for TextView

So your designer friend is back and she drops you a hot new design.  Due to a branding declaration from a highly-paid branding consultant, your whole app needs to use this new typeface.

Screen Shot 2016-05-24 at 8.01.33 AMOk, probably not the whole app, just a few titles.

Here’s the catch though — Android doesn’t ship with hot new typefaces like Uptown Sans, so you have to figure out how to convince TextView to render with it.  The goal is to make setting the font as easy as every other attribute on a TextView.  

before-customYeah, lint is having none of that; see the highlight?  And it’s just going to be ignored by TextView.  But hang with me for a couple minutes and you’ll get there.

Step 1. Copy your .otf into your assets folder

assets-folderStep 2. Copy this class into your project… Build… Breathe… we’re almost there…

We don’t want to go to the effort of rewriting TextView from scratch, it gives us so much.  We just want it to accept custom fonts from our layout XML.  So we extend.  Embrace, extend… embiggen? It’s something like that, I’m pretty sure.  Enfranchise?  Embark?  Empower?  Yeah, empower, that has to be it.

Step 3. You need to add this to your attrs.xml, or create res/values/attrs.xml with this if you don’t have one already

Step 4. Back to the layout file – but with two adjustments

layout

That’s it.  Build & run, and you’re done.

Extra Credit.

But wait, you say.  DRY that up, right?  Yeah, let’s do.  You don’t want to have the type in the whole path to the font in every layout file, isn’t that what auto-complete is for?  So let’s kick it up a notch.  Now I want two weights of that typeface, and the ability to easily reference one or the other.

We need to adjust your attribute to be an enum, instead of a string.  Here’s the new version:

Then in the custom TextView, we can dereference those.

And we’re there.  See?  Not that hard.

Yeah, so…

  • “There are other ways to do this!”
    • Agreed.  There are others like it, but this one is mine.  Tweet @ me with better solutions.
  • “Why not just use a TextView in the XML and use setTypeface() to change the typeface?”
    • You totally could.  I prefer to keep layout stuff in my layout files for code architecture reasons.

 

What did I miss?  Seriously, tweet @ me.  Half of the reason I wrote this article was because this feels like way too much work, so if you’ve got a better solution that I overlooked, I’d love to hear about it.

Android dev tip: Replace PNG assets with XML drawables

tl;dr: You’ll save a lot of memory.

The best way to fix OutOfMemoryException problems in Android is never to have them, so it’s important to be proactive about limiting the amount of memory that your app uses.  Sometimes this means bossing around your designers.  Let me explain why with a story…

button

Your designer hands you a design with a PNG that looks like this (well, hopefully your designer hands you things that look nicer than this, since I have no idea what I’m doing, but let’s ignore that for a minute, shall we?  K thx.)

It’s just a little thing, just 300×100 dp.  So you lay out the screen, run the app and everything is hunky-dory, until you look at the Memory Monitor in Android Studio and notice your app’s memory usage just jumped by about 1 MB.

png-mem-jump

What the hell just happened?

That’s no good.  Surely adding a simple button can’t cost a megabyte of memory.

finder-smallYou look at the PNG you just added, but it’s only 10 KB.  That can’t be the problem, can it?  Turns out, it is.  What you’re looking at in Finder is the compressed image file, but Android doesn’t keep the file compressed when it loads.  It renders your PNG to a Bitmap, which is the most un-compressed way to store an image.  It’s just a big matrix of pixels with a color value for each pixel.  By default, Android uses the ARGB_8888 format which uses 4 bytes per pixel.  And oh yeah, we’re looking at an XXHDPI device, so our 300dp width is actually 900 pixels.  That means our “little” 900×300 pixel image is using 1,080,000 bytes (1.03 MB) for its Bitmap.  

mem-dump-byte-array

Yeah, that really sucks.

So are you stuck with the sad fact that you’re now 1 MB closer to exploding your app by running out of memory?  Do you DM your designer on Slack and tell them they’re a bad person and they’re killing the app?  (Pro-tip: don’t ever do that)

There’s a better way.  You can draw the same thing to the screen using an XML Drawable and a Button.

Now let’s check that memory usage again.

xml-tiny-jumpOur XML-based drawable is using 504 bytes in memory.  Oh that’s nice.

Moral of the Story

Now obviously this won’t work for every asset; once you get past basic shapes, you’ll still need assets for anything complex.  But by being vigilant, and replacing simple assets with XML drawables, you delay the time when you’ll face the inevitable OutOfMemoryException.

4865622

Android InputTypes and Keyboards

When reading input from an Android user with an EditText, you have a simple way to help that user out by setting the InputType.  If you need the user to input a number, for example, you set the number InputType, and the user will automatically key a numeric keypad instead of the full QWERTY.  This saves the user a little bit of time and mental energy, and helps avoid mistakes with input.

Beyond just text and numbers, though, are a range of options that produce very subtle changes in the keyboard that Android brings up.  Below I explore which options bring up which keypad by default.

Screenshot_2015-04-10-12-04-55First, the standard keyboard, which covers a lot of the input types.
TYPE_CLASS_TEXT
TYPE_TEXT_VARIATION_EMAIL_SUBJECT
TYPE_TEXT_VARIATION_LONG_MESSAGE
TYPE_TEXT_VARIATION_PERSON_NAME
TYPE_TEXT_VARIATION_POSTAL_ADDRESS
TYPE_TEXT_VARIATION_PASSWORD
TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
TYPE_TEXT_VARIATION_WEB_EDIT_TEXT
TYPE_TEXT_VARIATION_FILTER
TYPE_TEXT_VARIATION_PHONETIC
TYPE_TEXT_VARIATION_WEB_PASSWORD

Screenshot_2015-04-10-12-05-02For our first subtle variation, the URI keyboard replaces the comma with a slash.
TYPE_TEXT_VARIATION_URI

Screenshot_2015-04-10-12-05-07Next, the email keyboard replaces the comma with an @.
TYPE_TEXT_VARIATION_EMAIL_ADDRESS
TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS

Screenshot_2015-04-10-12-05-23The short message keyboard replaces the enter key with emoji access.
TYPE_TEXT_VARIATION_SHORT_MESSAGE

Screenshot_2015-04-10-12-06-22The other main keyboard is for numeric entry.
TYPE_CLASS_NUMBER
TYPE_NUMBER_FLAG_DECIMAL
TYPE_NUMBER_FLAG_SIGNED

Screenshot_2015-04-10-12-06-40The number password variant reduces the available symbols and focuses just on the numbers.
TYPE_NUMBER_VARIATION_PASSWORD

Screenshot_2015-04-10-12-06-56The phone class adds some symbols common for phone number formatting, plus star & hash.
TYPE_CLASS_PHONE

Screenshot_2015-04-10-12-07-17The date/time class gives you a slash and colon for formatting.
TYPE_CLASS_DATETIME

Screenshot_2015-04-10-12-07-23The date variant only allows for a slash.
TYPE_DATETIME_VARIATION_DATE

Screenshot_2015-04-10-12-07-29The time variant only allows a colon.
TYPE_DATETIME_VARIATION_TIME

Introducing TimeoutOverride

The screen timeout for Android Wear is rather short, so I wanted to extend it for my app.  So I wrote a library to extend the screen timeout for an arbitrary number of seconds, and re-extend that timer automatically whenever the user touches the screen.  Usage is a one-line addition to your onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    new ScreenTimeoutOverride(20, getWindow());
}

Clone TimeoutOverride on GitHub to get started.

Your Smartphone is the Brain, Everything Else is an Appendage

At their I/O conference, Google announced Android Wear, Android Auto, and Android TV.  As I watched the series of announcements, I was struck with this metaphor: your smartphone is the brain, and everything else is an appendage.  Your watch will give you notifications at a glance and take voice commands, but it’s really just funneling that data back to your phone. Android Auto will bring navigation and music control into your car’s dashboard, but it’s just mirroring the maps and music streams from your phone.  Android TV will play movies and search through IMDB, but your phone is the remote control.

All Five Senses (well, 3 out of 5 ain’t bad!)

Our brain doesn’t see or feel or move us directly.  It processes a signals from my nose that smell bacon, then sends signals back out to my legs that say “I want to go to there” and I start walking.  Likewise, my phone doesn’t track my steps, it’s using a sensor in an Android Wear device to log that info, then relay it back to the phone to make sense of it.  Then the phone/brain can say “well, it’s 6PM and you’ve only walked 6,000 steps today, it’s sunny and 75, so grab the dogs and go for a walk.”  It sends out a notification that interrupts me browsing Instagram and gets me moving.

We have virtually replicated three of the senses; we have cameras (sight), microphones (sound), and touchscreens (touch).  Our phones have sensors for all three, and these appendage devices tend to have at least two.

Input & Output

I got on board the Android train back with the G1, and I remember thinking how powerful this device was, even with that rough first-gen hardware.  In the office I was working on a simulator for a $25,000 drone platform for the Marine Corps, but for a couple hundred bucks I had just bought a computer fully integrated with a fast internet connection, location and orientation and acceleration sensors, hi-res E/O sensor (you’d call this a camera), proximity sensor, 2D touch sensor, and keyboard.  I could read the signals from all of these sensors, process them however I wanted, then feed signals back out using the display, LED lights, vibration, or sound.

Since then phones have added a few more inputs (fingerprint sensors, heart rate monitors, multiple cameras for 3D).  What we saw at I/O was a proliferation of these.  Android Wear adds inputs (voice, step counter, wrist motion, heart rate, touch) and outputs (display & vibration on your wrist).  Android Auto uses your car’s display and audio system for I/O.  Android TV uses your existing TV to add a 50″ display to your smartphone.

Why these new Appendages Matter

Some of these might seem like minor additions (why do I need a display on my wrist when my phone is right in my pocket?), but the power is in the context.  If I’m bored in the office, sure, I don’t mind pulling out my phone and reading through a stream.  But if I’m driving a car, looking down at my phone is a seriously dangerous distraction.  If, instead, I can tell my wrist “OK Google, navigate to my next meeting”, without taking my eyes of the road, we’ve enabled the brains of your smartphone to help in a new context where the smartphone itself can’t get the job done.

This may not be as life-changing as the jump from features phones to smart phones, but it is still an improvement.

Flipping the Network

I once worked in a lab where they wanted any user to be able to sit at any computer and start working.  So I was issued a hardware token (think of a smart card, or a USB plug – holding my private key) that I could plug into a computer; it would recognize me, load in my environment and preferences, and I could pick up working wherever I left off.  The central brain was in a server room, but I could use whatever computer was in front of me for I/O.  With Android, we’re flipping that around.  I can still use whatever device is handy for I/O, whether that’s my watch, my TV, my car; but now the central brain is sitting in my pocket with the phone, rather than in a server room.

So What

My point is that these new appendages shouldn’t be viewed on their own. They’re not replacements; you’re not going to get rid of your phone when you get a new watch.  Instead, the watch becomes additional input and output for your phone.  So don’t think of the watch’s utility as a watch, think of what it can do as extra I/O for your phone.

Jenkins CI broken on upgrade to Mac OS Mavericks

Putting this out there in case somebody has the same problem.  I upgraded my Jenkins box to OS X Mavericks, and Jenkins stopped responding; requests to localhost:8080 simply dropped.

After a bit of digging and dead ends, I found out that java wasn’t installed.  Running

javac -version

from the command line failed, and asked me to install Java.  I installed the lastest JDK, restarted jenkins with these commands:

sudo launchctl unload -w /Library/LaunchDaemons/org.jenkins-ci.plist
sudo launchctl load -w /Library/LaunchDaemons/org.jenkins-ci.plist

and everything seems to be back to normal.

End Of Life notice for Virginia Traffic apps

Four years ago, I got my first smartphone.  Being a commuter in Hampton Roads, one of the first websites I tried to visit was VDOT’s 511 traffic information site.  It wasn’t mobile-optimized at the time, so it was essentially unusable on a small touch device.  After weeks of hacking around, I built a server app to scrape their website for data and mobile apps to display that data.  Since then, I’ve slowly upgraded the app, adding features requested by users.

Unfortunately, two years ago I moved out of Virginia, so I no longer use the apps myself.   VDOT, whose data I rely on for the app, has occasionally made changes to their data feed which require significant rework on my part to keep the apps going.  Note: this is entirely VDOT’s prerogative, and I in no way criticize them for doing so.

The end result of these two factors is that my apps no longer provide an acceptable experience to the user, and I don’t have the time to spend on fixing them up.  So it’s with regret that I have removed my apps from sale in the App Store and the Play Store.  I will continue to leave the server running for now; if you already have the app installed on your phone, it should keep working, at least as well as it currently works, for the foreseeable future.

The good news is that last year VDOT published their own apps to get Virginia Traffic information.  I suggest you check out these apps as a replacement for mine.  You can find more information about VDOT’s mobile apps on their website.

I want to thank all of the users who provided encouragement, positive feedback, and suggestions, and to thank VDOT for allowing me to scrape their data for so long.  These apps were the first step on the journey that has led to my current role developing mobile apps full-time.

And as always, please only use your phone while you’re parked.  Don’t cause an accident by checking your phone while you’re driving.  There’s really no need.