OkHttp + Restricted APIs

Certain TLS features like Server Name Indication (SNI) and Application-Layer Protocol Negotiation (ALPN) existed in Android before they had public APIs. The code was there; there just wasn’t a good way to use it. OkHttp hacks around such limitations with reflection. Our internal platform package integrates both Android and…

KitKat and TLSv1.2

TLSv1.2 came out in 2008 but Android didn’t get support for it until Android 5 in 2014. Previous releases including Android 4.4 KitKat support up to TLSv1.1 by default. KitKat’s old TLSv1.1 isn’t secure enough and so its retirement has been planned for…

Modeling States vs. Facts

Lots of object models primarily track application state. For example, OkHttp’s Http2Connection.kt has state for whether a ping’s reply is outstanding: private var awaitingPong = false This is set to true each time a ping is sent and then false again when its reply is received. I’ve…

Naming Versions

I’m working on some code to sort software versions and it’s tricky. Maven Software that releases to Maven Central should follow Maven’s versioning scheme. This list is sorted by Maven’s scheme: 1.0.0-alpha 1.0.0-beta 1.0.0-rc1 1.0.0-RC2 1.0.0…

HTTP in a Hostile World

I presented this at Droidcon Toronto on November 13, 2019. Available as video, slides, YouTube, & Speaker Deck. Networking on Android is difficult work. We need to display fresh data and rich media while limiting our network use. Unfortunately cookie-cutter solutions are not acceptable. In this talk we’ll: 🥌 Verify…

Kotlin’s Assert Is Not Like Java’s Assert

OkHttp uses synchronized as an allocation free mutex. Our concurrency model is tricky enough that we’ve documented the rules! And if we forget the rules, we also use runtime assertions to catch mistakes: @Override void flush() { // Make sure we don’t hold a lock while doing I/O! assert…

A Dependency Injector’s 3 Jobs

You can do dependency injection (DI) manually or with a library. Constructing your application’s dependency graph by hand is a cute exercise but not practical beyond toy examples. You’ll eventually find yourself extracting the repetitive manual DI code into your own bespoke library, one that’s likely to…

Value Objects, Service Objects, and Glue

This post expands on a section in my Writing Code That Lasts Forever talk. When I was learning object oriented programming I struggled to define boundaries between classes. Should a Chess game’s Bishop class have a move() method to reposition itself on the board? Should there even be a…

Factory or Extension Function?

I’m working on OkHttp’s Kotlin upgrade. Java callers use this code to go from a String to an HttpUrl: String string = ... HttpUrl httpUrl = HttpUrl.get(string); Should it remain the same in Kotlin? val string: String = ... val httpUrl: HttpUrl = HttpUrl.get(string) or should we follow the core…

Metrics for OkHttp’s Kotlin Upgrade

We’re upgrading OkHttp’s implementation language from Java to Kotlin. It’s a big process, especially as we’re maintaining strict compatibility with OkHttp 3.x. Fortunately we’ve done it before and we’re following the strategy Egor & I presented last year. Today we reached a nice…

JSON Explained

I presented this at Chicago Roboto on April 26, 2019. Available as code, video, slides, YouTube, & Speaker Deck. Java and Kotlin coders: note this talk. Its tran- script describes some tools to encode any object. I’ll review the libraries including an an- notation that can make your app…

Syntactic Sugar

In comparing programming languages I’ve found myself anchoring on what I’m comfortable with and seeing everything else as either “low level and verbose” or “full of syntactic sugar and magical”. I’ve recently gone from using mostly Java to using mostly Kotlin and I’ve learned that syntactic…

Toehold Test

Let’s write a small class that has potential to grow. data class ZipCode(val code: String) { init { require(code.matches(Regex("""\d{5}"""))) { "not a zip code: $code" } } } Should you write a unit test for this? Turbo test-driven developers do because…

Deadlines

My recent work requires coordinating teams to build their own pieces of a larger puzzle. We’re going to replace old system 𝒂 with new systems 𝔁, 𝔂, and 𝒛, and that means each team needs to land their contribution on schedule. But in my heart I know that software hates schedules! We’re…

Live Forever

I don’t have a fountain of youth but instead a surprising approximation. You know the expression, “time flies while you’re having fun?” It’s almost right. Your brain’s perception of time flies when you’re doing something familiar. And most importantly, your perception of time slows when…

Weightloss

If you lose 10 pounds, where do those pounds go? It’s weird trivia that I never learned in school. Do you poop it out? pee? sweat? A parallel question clarifies: where does the gasoline goes when you drive your car? The car’s internal combustion engine turns oxygen and…

SQL Multiple-Column IN Clause

The IN clause is handy. I use it all of the time. SELECT * FROM cars WHERE make IN ('Ford', 'Subaru') AND price < 5000; +--------+---------+------+--------+-------+ | make | model | year | color | price | +--------+---------+------+--------+-------+ | Ford | Focus | 2007 | Black | 1100 | | Ford | Mustang | 2005 | Yellow | 4000 | | Ford…

Developer Identity & Multiplatform

We don’t self-identify as software developers but as web developers, backend developers, Android developers, or iOS developers. Many factors reinforce this specialization. I’m a Droid Building systems builds experience. Android developers learn technologies that have no analog on other platforms: activities, intents, and XML layouts. Once we’ve…

Writing Code That Lasts Forever

I presented this at Droidcon NYC on August 28, 2018. Available as code, video, slides, YouTube, & Speaker Deck. Developers are perpetually fighting yesterday’s code. We need to conquer our immortal fears and build programs that evolve gracefully. In this talk we’ll: 🗿 Discuss code that anticipates the future…

Ok Multiplatform!

I presented this with Egor Andreevich at Droidcon NYC on August 27, 2018. Available as video, slides, YouTube, & Speaker Deck. Okio is a small library that powers a lot of Square’s open source software, such as OkHttp, Moshi and Wire. Okio makes I/O easy by solving the…

URL Encoding Is Material

Lots of OkHttp and Retrofit users have reported bugs complaining that URL special characters (like + ; | = * ; ; | or *) weren’t encoded as they expected. Why can’t HttpUrl just encode ; as %3B? Extra escaping is safe in most programming languages and document formats. For example, in HTML there’s no behavior consequence…

Coordinating Space and Time

I presented this at Chicago Roboto on April 20, 2017. Available as code, video, slides, YouTube, & Speaker Deck. One of Android’s core requirements is that the UI runs on the main thread and IO in the background. Though concurrency is powerful, it’s also frustrating to deal with…

A Clever, Flawed OkHttp Interceptor Hack

All of OkHttp’s configuration is on the OkHttpClient instance: OkHttpClient client = new OkHttpClient.Builder() .readTimeout(2_000, TimeUnit.MILLISECONDS) .writeTimeout(2_000, TimeUnit.MILLISECONDS) .cache(new Cache(cacheDirectory, cacheSize)) .build(); This design is minimal and simple. There aren’t any precedence rules or hidden settings to be surprised by.…

Canonical URLs for Javadocs

We publish separate Javadocs for each major release of OkHttp: 1.x, 2.x, 3.x. This is intended to help you out when you’re using an old version. But it’s had an adverse side-effect: Googling for “responsebody okhttp” only returns results for old versions. You see the…

Story Code

Designing APIs is hard. One technique that helps me is to tell a story with the code: I’ll make a sequence of calls to show how things fit together. I find this helps me to discover what methods I need and what I can leave out. Using features together…

Name Your Threads

I work on a big Java service that does lots of things. When I snapshot the application’s threads I can see it’s got lots going on: Talking RPC and HTTP Running cron jobs and job queue jobs Persisting to MySQL Coordinating with ZooKeeper Collecting garbage At a glance…

Seductive Code

It’s careful work balancing tradeoffs when writing code and designing APIs. Here’s some everyday Java code: for (Protocol protocol : protocols) { if (protocol != Protocol.HTTP_1_0) { result.writeByte(protocol.toString().length()); result.writeUtf8(protocol.toString()); } } On Android—where garbage collector costs aren’t necessarily negligible—I make my…

Jesse, Learning in Anger

I’m using an open source library and it crashes in an unexpected way. The crash makes me grumpy because it prevents me from getting my real work done. I don’t want anyone to face this indignity ever again! And so I proceed to report the bug to the…

Decoding the Secrets of Binary Data

I presented this at Droidcon NYC on September 30, 2016. Available as code, video, slides, YouTube, & Speaker Deck. Opaque blobs of data have hexed Android programmers for too long. It’s time to byte the bullet and learn how data is transmitted and persisted. In this talk we’ll:…

Charles 4 has HTTP/2

Karl von Randow has released Charles 4. “With Charles 4 you can now see HTTP 2 working, and you can use all of your familiar tools; Repeat, Breakpoints, and so on. You’ll spot HTTP 2 hosts in Charles as they use a different icon—with a lightning bolt!” I…

Java’s new HTTP client is upside down

One of Java 9’s new features is a replacement for HttpURLConnection. And while I’m thrilled to get rid of that old garbage its replacement has its own surprises. The Good The API is small. The new package is java.net.http and the Javadoc shows only 12 new…

The Last HttpURLConnection

An awkward API OkHttp 1.0 started out as an optimized implementation of HttpURLConnection. This old API is awkward to implement because there is an implicit state machine that corresponds to the underlying network I/O. GET / HTTP/1.1 Host: publicobject.com Accept: text/html HTTP/1.1 200…

The Open Source Maintainer’s Dilemma

We’re in a golden age of reusable open source code. With GitHub and Maven Central it’s never been easier to create and share code. This is excellent! Android developers have access to a steady stream of new projects. I keep up by following some Android developers on Twitter…

Disable Cleartext in OkHttp

Alex Klyubin posted instructions on disabling cleartext networking in Android’s built-in HTTP stack. Ideally, your app should use secure traffic only, such as by using HTTPS instead of HTTP. Such traffic is protected against eavesdropping and tampering. Unfortunately that approach requires Android 6 or better. But if you’re…

Deliberate Disobedience

Some friends and I do regular boardgame nights. Our favorite is Tichu. The first few times we played we got the rules wrong: we thought certain plays were legal but they weren’t. By playing more, studying the rules, and Googling the edge cases, we eventually got the rules right.…

Reflection-friendly Value Objects

There’s plenty of good advice on how to do value objects well in Java. Ryan Harter’s AutoValue intro is particularly handy. When I’m not using AutoValue, I like to do my builders as recommended in Item 2 of Effective Java Second Edition. In it Josh Bloch recommends…

Reflection Machines

Conventional wisdom says that reflection is slow and that it should be avoided. As always, the truth is more nuanced. Let’s start with some code. class Movie { static final List<Movie> BEST_MOVIES = Arrays.asList( new Movie("Back to the Future", 1985), new Movie("…

Ceilings & Floors

I’ve been thinking about policies and incentives. A lot of motivation comes down to ceilings and floors. Floors: the worst case. We want to raise the floor, limiting the pain in the worst case. Minimum wage is a floor on labor. Ceilings: the best case. We also want to…

OkHttp Certificate Pinning Vulnerability!

Bad news. When I added certificate pinning in OkHttp 2.1, I didn’t sanitize the server’s certificate chain. An attacker could exploit this weakness to defeat the protection offered by certificate pinning. The vulnerability was disclosed to Square by security researcher John Kozyrakis. Whew! We fixed it in…

LinkedHashMap is always better than HashMap

Deterministic code is much easier to debug & understand than non-determinstic code. Got a test that’s failing? Launch the debugger, step through the code, and find the exact statement where an assumption is violated. For me this often looks like a binary search. I add breakpoints and make assertions…

Your strict naming conventions are a liability

Programmers tend to be pretty obsessive over consistency. Most of that consistency is worthwhile, but some of it is foolish. For example, let’s take some JSON from GitHub’s gists API: { "files": { "Hello.txt": { "type": "text/plain", "content": "…

Sneaking Data into an OkHttp Interceptor

OkHttp Interceptors are a fun & powerful way to implement cross-cutting behavior in your app. You can use ’em for authentication, performance, monitoring, and more. There’s even open source interceptors for OAuth signing and curl logging! Suppose we want to write an interceptor that tracks which activities use the…

The Play Store is bad at their job

Today Google removed Podcast Addict from the Play Store. Sometimes people publish podcasts containing sexually explicit material, and Podcast Addict is capable of accessing such material. “Podcast Addict was the #1 podcast app on the Play Store with 4M downloads, 175K reviews and an average rating of 4.6/5…

4 Brainy Books

Like books? I don’t have the attention span for reading but I listen to plenty of audiobooks. Here are some of my all-time favorites. On Intelligence Non-fiction by Jeff Hawkins How your brain works. Amazon, Audible Daemon Fiction by Daniel Suarez In Terminator, Skynet just launches the nukes. In…

OkUrlFactory is going away

OkHttp exposes three APIs: Request/Response. This is the most fully-featured API. It can be used synchronously or asynchronously. It avoids mutable state. Plus interceptors! OkUrlFactory, the HttpURLConnection API. This is a complete implementation of an awkward API. The API’s awkardness has resulted in an implementation that is complex…

com.squareup.okhttp3

We’re about to start working on OkHttp 3.0. It’ll be like OkHttp 2.7, but with small backwards-incompatible API changes. For example, we’re going to make multipart better. How can we roll this out without breaking everything? As Jake explains, we’re going to cheat! By…

JNI Hello World

I presented this at Android KW on December 3, 2015. Available as video, slides, YouTube, & Speaker Deck. A quick look at what JNI is, how it works, and how you can use it to be awesome.…

A Convincing Argument

I’m always disagreeing. I think this might be inevitable. The stuff we agree on is boring, and so the conversation accelerates until it slams into something interesting: a disagreement. With a neighbour: climate change. With a family member: basic income. With a colleague: HBase. With a friend: messaging software.…

Don’t use interfaces for values

If you’re defining an Java API, value objects are your friend. And interfaces aren’t suited to that task. Java gets this wrong all over: Annotations. They use interfaces to define value objects, and consequently it’s quite awkward for tools like Guice to define annotation values. NamedImpl.java…

Publishing Javadoc for GitHub Projects

I recently standardized the location of Javadoc for several of Square’s Java open source projects. Here’s a sample: https://square.github.io/picasso/2.x/picasso/ https://square.github.io/retrofit/1.x/retrofit/ https://square.github.io/retrofit/2.x/retrofit/ https://square.github.io/wire/2.…