Menu

Checked exceptions vs. API design

Java has checked exceptions and unchecked exceptions.

Checked exceptions are for expected problems that you should deal with and recover from at runtime. Flaky network? Catch the IOException and deal with it.

Unchecked exceptions are for unexpected problems that should trigger a crash. Is the byte count negative? Got a string when you expected a URL? Don't recover; just crash. In 2015 even crashing is luxurous with cloud services to make failure delightful.

But when designing general purpose APIs, it's not always possible to differentiate unexpected vs. expected problems. The classic example is NumberFormatException. When you accept raw data from a user and Integer.parseInt() fails, you probably shouldn't crash. But if you're parsing a trusted JSON file and the input is malformed, you should give up so the problem can be found & fixed.

Today I'm annoyed because I'm parsing data that will be clean sometimes and dirty at other times. Do I risk crash good programs on bad input? Or do I punish safe calls with needless try/catch ceremony?

Guava works around this in LoadingCache with two methods that only differ in the types of exceptions they throw: get() and getUnchecked(). This both works and is sad

How do HTTP caching heuristics work?

Suppose you’ve requested a webpage with a Last-Modified date and no other caching headers:

HTTP/1.1 200 OK  
Last-Modified: Tue, 16 Dec 2014 06:00:00 GMT

...

The HTTP client will happily store this response in the cache indefinitely. But it won't serve it from the cache unless it’s still fresh at the time of request.

How do we decide whether it’s still fresh? There are three timestamps we’re interested in:

  • Last requested at: Timestamp when we made the last request.
  • Last modified at: What the Last-Modified header said on that response.
  • Now: Timestamp at the time of the current request.

We use the time between last requested at and last modified at to estimate how frequently a document is edited. If a page was modified 5 minutes before the request, it’s assumed to be frequently modified. If it was last modified 5 years before the request, it’s assumed to be infrequently modified.

A page is fresh for 10% of that duration: 10% of 5 minutes is 30 seconds; 10% of 5 years is 6 months. A page is considered fresh until that 10% has elapsed since the document was last requested.

An

Tracking OkHttp Download Progress

Anton Rieder just contributed an OkHttp code sample that monitors a download’s progress using an interceptor. With it, you get a callback as bytes arrive:

  interface ProgressListener {
    void update(long bytesRead, long contentLength, boolean done);
  }

I like this example because it’s all layered decorators:

  • The Interceptor puts code between application-and-OkHttp, or OkHttp-and-network.
  • The ResponseBody augments the response body to support progress tracking.
  • The Source does the work: updating the progress listener as bytes are delivered from network to application.

In each case, the adaptable interface is deliberately limited. Decorating okio.Source is easy! To contrast, InputStream is hostile to decoration.

OkHttp 2.3 has HTTP/2

Lately I've been building HTTP APIs for Square Cash, to be used by our website and partners like Snapcash. It turns out this is a particularly difficult task because I need to balance two competing concerns:

Keep separate things separate. If the app wants to look up payments 123, 246 and 369, it should make three requests for /payments/123, /payments/246, and /payments/369. This is simple and manageable, but it means both client and server need to pay HTTP call overhead for every payment. That slows down the experience and increases our datacenter load.

Batch things up. REST APIs are nice and all, but what's going to run fastest is a aggregating everything into a single call. Perhaps it’s /payments-list/123,246,369 and now there’s more APIs to worry about, but fewer calls.

Since /payments-list/123,246,369 doesn’t quite identify a resource, batching things also makes it more difficult to use HTTP caching. If the browser later wants to load payments 246 and 482, the URLs won’t match and we have to do our own caching in the application layer.

Enter HTTP/2

By significantly lowering the per-call overhead, we can use

Okio 1.3 has segment sharing

Okio’s buffer reads like an InputStream: when you read 50 bytes from the buffer, you implicitly remove those bytes from the buffer. This is a handy optimization and it means we can move data rather than copying it by default.

But sometimes you need non-destructive reads. So in Okio 1.3 we've changed the Buffer.clone() method to do segment sharing. Previously, cloning a 2 megabyte buffer would require 2 megabytes of memory to be allocated and copied. With segment sharing, only the bookkeeping data is copied, which is about 3% of the size of the buffer’s data.

To read a buffer without consuming it, just create a (cheap) copy and read that. And our fundamental optimization is preserved: reading from the clone will move data rather than making even more copies.

Okio 1.3 also adds some nice ergonomic features to ByteString:

  • URL-safe Base64 encoding
  • Handy MD5 and SHA-256 hashes
  • Substrings!

There’s also new APIs in BufferedSource and BufferedSink:

  • Read and write signed decimal values without the string intermediates that you'd need with Long.valueOf(String). We can use this in DiskLruCache’s journal file, among other places.
  • Read and write unsigned hexadecimal values, also without

Custom Java Trust Stores without Bouncy Castle

Java’s crypto APIs are flexible and powerful. But just awful to use. There are too many contexts, managers, factories, and providers. Want a certificate? Take your pick!

Gross.

Suppose you want to replace the host platform’s (scary) set of trusted certificate authorities with your own trimmed down set. This happens if you want to do HTTPS without paying a certificate authority each time your configuration changes. (You’d use certificate pinning if you wanted to avoid trusting all certificate authorities).

Most of the online advice I've seen suggests that you need Bouncy Castle and/or keytool to first load the PEM files into a JKS or BKS keystore, which you then use to build an SSLContext. That's annoying because it adds another opaque binary file to an already confusing process.

Fortunately, you can skip that step and read the PEMs directly. Hidden in plain sight within the certificate APIs is a mechanism to build an SSL socket factory from a PEM file like this one:

-----BEGIN CERTIFICATE-----
MIIFVTCCBD2gAwIBAgIRAKgHBM+t9Yx3v9G9tGZECWkwDQYJKoZIhvcNAQELBQAw  
b21haW4gQ29udHJvbCBWYWxpZGF0ZWQxFDASBgNVBAsTC1Bvc2l0aXZlU1NMMRkw  
FwYDVQQDExBwdWJsaWNvYmplY3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A  
oqEld6bOSoMlYavj9GCBSNIx2+mGS0Tg6A==  
-----END CERTIFICATE-----

OkHttp's CustomTrust example has

proto3 + JSON are a great match

On Cash we communicate with the web and mobile apps via both protocol buffers and JSON. For both data formats, we use proto2 as a schema language. It defines what our message types are, what their fields are, and gives us a language-neutral place to document all the things. This approach is very lowest-common-denominator: we can't use features that JSON lacks (default values, bytestring values) nor those that proto2 lacks (map types). It’s imperfect but productive!

Google recently released an alpha of proto3, which is very suited to our use case. It sheds features that JSON can't express and adds a map type. This is fantastic.

Here's a sample of proto3 output if you're curious. The code generated by the alpha looks & works like the code from proto2.

I think the Wire generated code is still the best API for most projects. We'll add support for proto3 once the syntax & feature set is final.

Droidcon Montréal, April 9–10

I'm proud to share the keynote stage with Jake at Droidcon Montréal this April. We're planning to talk about open source. That’s a broad topic, and one I’ve presented on previously.

But it isn’t just about bug reports and pull requests. I’m thinking a lot about what Ashe Dryden said in The Ethics of Unpaid Labor and the OSS Community:

“OSS contribution takes time; I don't think anyone would contest that. Getting familiar with a project, finding out where you can fit into it, reading and responding to issues, testing and submitting patches, writing documentation. All of that requires a good deal of time.

Marginalized people in tech - women, people of color, people with disabilities, LGBTQ people, and others - have less free time for a few major reasons: dependent care, domestic work and errands, and pay inequity.”

Yikes. I’ve been doing open source for a decade, but only because I’ve had the privilege of time & resources to do so.

It’ll be an interesting conversation, and it’s happening at Droidcon Montréal April 9–10. Early bird registration ends January 31!

Fancy Flow Control: Did it throw?

Exceptions are powerful control flow: mainline code handles the mainline cases, and exception cases can be handled elsewhere. But sometimes you want to observe whether an exception occurred, without necessarily handling that exception.

For example, suppose we're writing a service that sends webhooks to a far-away webserver. Webhooks are naturally flaky: there are usually many target servers, each managed a different team with a different expectation of availability and correctness.

Our method wants to run webhooks and keep statistics on their results:

public int sendWebhook(String url, String request)  
    throws IOException {
  try {
    int statusCode = httpPost(url, request);
    if (statusCode >= 400) {
      failureCount++;
    }
    return statusCode;
  } catch (IOException e) {
    errorCount++;
    throw e;
  }
}

What happens if httpPost() throws an unchecked exception, like WebServiceException? Well, we can handle that too. And also Error so that assertion failures aren't dropped:

public int sendWebhook(String url, String request)  
    throws IOException {
  try {
    int statusCode = httpPost(url, request);
    if (statusCode >= 400) {
      failureCount++;
    }
    return statusCode;
  } catch (IOException | RuntimeException | Error e) {
    errorCount++;
    throw e;
  }
}

This works. But it's unfortunate to list the three different Throwable types that can pass-through this method, especially if those types could change. Should we add another checked exception like URISyntaxException, it's easy to lose

Okio Watchdog

I was running a jstack dump on my project's app server this afternoon & I saw Okio Watchdog among the threads:

"Okio Watchdog" #1972 daemon prio=5 os_prio=0 tid=0x00007f4a8c01e800 nid=0x362 in Object.wait() [0x00007f48f2351000]  
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at okio.AsyncTimeout.awaitTimeout(AsyncTimeout.java:297)
    - locked <0x0000000733eaa0e0> (a java.lang.Class for okio.AsyncTimeout)
    at okio.AsyncTimeout.access$000(AsyncTimeout.java:40)
    at okio.AsyncTimeout$Watchdog.run(AsyncTimeout.java:272)

This is a thread Okio uses to implement fancy timeouts for OkHttp.

The JDK's Network Timeouts

There are two timeout mechanisms in Java's networking stacks:

Notably, there's no API for write timeouts on blocking I/O. Oracle advises you switch to NIO if you need that.

Okio Timeouts

Okio uses a watchdog thread to implement read & write timeouts for blocking I/O. When the watchdog sees that an operation has gone on too long

Posting Images on GitHub's wiki

GitHub's wiki permits embedded images, but offers no UI to upload your own images. Here's how to do it from the command line.

Clone the Wiki's Git Repo

GitHub's wiki is itself a git repository. Clone it to your desktop using an SSH URL to make git push just work later. (This assumes you're already configured SSH keys with GitHub).

Here I'm editing the wiki for square/okhttp. Substitute square with your GitHub username or organization, and okhttp with your GitHub project.

git clone git@github.com:square/okhttp.wiki.git  
cd okhttp.wiki/  

Add the image

There's no pull requests or other process here. Just push master once you've added the image.

mv ~/Desktop/interceptors@2x.png ./  
git add interceptors@2x.png  
git commit -m "Add interceptors diagram."  
git push  

Embed the image

Raw wiki resources are web-accessible at raw.githubusercontent.com. The URL for my image is here and the corresponding markdown is this:

 ![Interceptors Diagram](https://raw.githubusercontent.com/wiki/square/okhttp/interceptors@2x.png)

I edited my wiki on the web; editing it in the local git repository also works. Just don't forget to push.

Enjoy

OkHttp 2.2 has Interceptors

When Josh Bloch measures an API, he evaluates its power to weight ratio: great APIs let you accomplish a lot (high power) without much mechanism (lightweight).

Interceptors are a new feature of OkHttp 2.2. There isn't much mechanism: two interfaces and four methods:

public interface Interceptor {  
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();
    Response proceed(Request request) throws IOException;
    Connection connection();
  }
}

Use OkHttp's interceptors to hook into your application's HTTP calls. You get to see everything that's coming in and going out to the application (that's an application interceptor). Plus what goes out to and back in from the network (that's a network interceptor).

There is a dangerous amount of power here. Like magic, incredible cosmic power can accomplish great things when it is used carefully:

  • You can throttle incoming and outgoing bandwidth.
  • You can rewrite requests to compress them or sign them.
  • You can collect profiling data.
  • You can validate responses.
  • You can transform the response to workaround server problems.

And like magic, you can get yourself into trouble. Be careful! Read the interceptors doc and code examples to learn how it all works before you dive in.

Get it

The changelog has full details

YYYY

Étienne Vallette d'Osia tweeted about a surprising behavior lurking in SimpleDateFormat:

If you use SimpleDateFormat and “YYYY” for years (not “yyyy”), your code currently returns 2015 instead of 2014. Enjoy! (no pb w/ jodatime)

He's right.

SimpleDateFormat format = new SimpleDateFormat("dd-MMM-YYYY");

Calendar day1 = new GregorianCalendar(2014, Calendar.DECEMBER, 28);  
System.out.println(format.format(day1.getTime()));

Calendar day2 = new GregorianCalendar(2014, Calendar.DECEMBER, 29);  
System.out.println(format.format(day2.getTime()));  

That code prints:

27-Dec-2014  
28-Dec-2015  

Looks like Twitter for Android probably suffered this bug, and signed out all of its Android users.

This is working as intended! From the SimpleDateFormat docs:

Week Of Year and Week Year

Values calculated for the WEEK_OF_YEAR field range from 1 to 53. The first week of a calendar year is the earliest seven day period starting on getFirstDayOfWeek() that contains at least getMinimalDaysInFirstWeek() days from that year.

For example, January 1, 1998 is a Thursday. If getFirstDayOfWeek() is MONDAY and getMinimalDaysInFirstWeek() is 4 (ISO 8601 standard compatible setting), then week 1 of 1998 starts on December 29, 1997, and ends on January 4, 1998.

Yikes.

ntCoent-Length

Tonight I was looking around the web for examples of Content-MD5 in an HTTP response. I was thinking it'd make for another example of OkHttp's powerful new Interceptor API.

I haven't found such an example yet. But I did stumble upon some curious headers on Apple's CDN:

~ curl -v http://images.apple.com/ac/globalheader/1.0/styles/globalheader.css
> GET /ac/globalheader/1.0/styles/globalheader.css HTTP/1.1
> 
< HTTP/1.1 200 OK  
< ntCoent-Length: 89953  
< Transfer-Encoding:  chunked  
...

I'm guessing ntCoent-Length is an (obvious) misspelling of Content-Length. Weird. Typos happen.

But what's weirder still is that another file on the same host has a similar typo:

~ curl -v http://images.apple.com/metrics/ac-analytics/0.2/scripts/ac-analytics.js
> GET /metrics/ac-analytics/0.2/scripts/ac-analytics.js HTTP/1.1
> 
< HTTP/1.1 200 OK  
< nnCoection: close  
< Connection: keep-alive  
...

You say nnCoection, I say Connection. Now I have a puzzle: what would trigger a bug like this?

HTML-formatting Javadocs

Public APIs

I work on lots of public APIs. For those, it's nice to have nicely-formatted Javadoc, following the Guava guidelines. This means lots of <p> tags, {@code} blocks! Here's an example from Okio:

  /**
   * Wait at most {@code timeout} time before aborting
   * an operation. Using a per-operation timeout means
   * that as long as forward progress is being made, no
   * sequence of operations will fail.
   *
   * <p>If {@code timeout == 0}, operations will run
   * indefinitely. (Operating system timeouts may still
   * apply.)
   */
  public Timeout timeout(long timeout, TimeUnit unit) {
    ...
  }

Private Implementations

I also work on a large, not-open-source Java project: the Square Cash service. This project is developed by a team, and quite frequently I've been harassing my team to fix their darn Javadoc tags. Typically it's a missing <p> tag. Here's an offending example from our payment history query:

  /**
   * Returns payments for `customerId` in the named role
   * with the current client. We query senders and recipients
   * independently and merge the results in memory because
   * MySQL uses its indices this way and doesn't otherwise.
   *
   * This returns one more results than `maxResults` so the
   * caller can tell if another page should be offered.
   */
  List<PaymentRow> paymentsInRole

Dagger 2 has Components

Much of the Dagger vs. Guice comparison is about code generation vs. reflection. But they're also different in how they ask you to structure your application...

Guice

Guice apps are built with these fundamental abstractions:

  • Multiple injection points: dependencies, being injected.
  • Multiple bindings: dependencies, being provided.
  • Multiple modules: a collection of bindings that implement a feature.
  • One injector: a collection of modules that implement an application.

And then there's Guice scopes:

  • Unscoped: a new instance for each injection. Unscoped objects have the same lifetime of whatever injects them. Business logic classes like an SmsMessageValidator should be unscoped.
  • Custom-scoped: your business logic controls how injected instances are shared. For example, @RequestScoped gives you a place to share the state of an HTTP request. Context-dependent classes like a UserAuthenticator should be custom-scoped.
  • Singleton-scoped: one instance for the entire application. Shared resources like a DatabaseConnectionPool should be singleton-scoped.

Dagger 1

Dagger 1.x's fundamentals are similar:

  • Multiple injection points: same.
  • Multiple bindings: same.
  • Multiple modules: same.
  • Multiple object graphs: a collection of modules that implement a scope.

Dagger doesn't have custom scopes. Instead, we layer multiple object graphs.

  • One root object graph contains all of the application-wide stuff. Like the DatabaseConnectionPool.
  • Multiple custom

OkHttp 2.1

OkHttp 2.1 is out. The release candidate announcement explains that 2.1 is focused on caching & crypto.

The release has new APIs to customize TLS, giving you control of certificate pinning, cipher suites, and TLS versions. For example, now you can restrict an OkHttpClient to cipher suites that support perfect forward secrecy:

ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)  
    .tlsVersions(TlsVersion.TLS_1_2)
    .cipherSuites(
        CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
        CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
        CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
        CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
        CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
        CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
        CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
        CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
        CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
        CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
        CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
        CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
    .build();
client.setConnectionSpecs(Collections.singletonList(spec));  

(Note that perfect forward secrecy is already available by default and will be used where it can be negotiated. This

OkHttp 2.1 RC1

We've just cut the first release candidate of OkHttp 2.1. This release is focused on caching & crypto.

Caching

We've improved cache APIs and also fixed some long-lived cache bugs. If you're using OkHttp with Picasso, it may fix some unexpected cache misses. The cache is now private which allows it to store resources guarded with OAuth Authorization headers.

Getting the right Cache-Control is now easier, with constants for FORCE_CACHE and FORCE_NETWORK for the rare occasions when you need to override the default policy:

    Request request = new Request.Builder()
        .cacheControl(CacheControl.FORCE_NETWORK)
        .url("https://square.com/cash")
        .build();

Crypto

We've become quite opinionated on TLS configuration. We now expose a class, ConnectionSpec to manipulate which TLS versions are enabled (for example, to mitigate SSLv3's POODLE vulnerability) and also which cipher suites (for perfect forward secrecy). You can now disable TLS fallback and cleartext connections.

This release introduces an API for certificate pinning, though you should use it very carefully.

client.setCertificatePinner(new CertificatePinner.Builder()  
    .add("publicobject.com", "sha1/DmxUShsZuNiqPQsX2Oi9uv2sCnw=")
    .add("publicobject.com", "sha1/SXxoaOSEzPC6BgGmxAt/EAcsajw=")
    .add("publicobject.com", "sha1/blhOM3W9V/bVQhsWAcLYwPU6n24=")
    .add("publicobject.com", "sha1/T5x9IXmcrQ7YuQxXnxoCmeeQ84c=")
    .build());

Get it now

The changelog has full details of

From 99¢ to a 99¢ in-app purchase

My hobby app Rounds was 99¢ for its first 2 years. In September, I made a bunch of changes. I made the app free and instead offered a 99¢ in-app purchase to unlock a full palette of colors.

Blue is sales.
Red is current installs.

Note that current installs were depressingly small & flat for a very long time. As a small number new users purchased and installed the app, an equally small number of old users uninstalled and moved on.

Going free yielded a nice spike in installs, but no equivalent bump in sales. Ratings are also down from 4.8 stars to 4.5, mostly due to a handful of drive-by one-star reviews.

Clearly I need to figure out how to improve conversion.

Against Fragments

Pierre-Yves Ricau:

“The backstack isn't an activity specific notion; you can implement a backstack within an activity.”

Great advice. Fragments are too complicated to be worthwhile for simple apps. But they're also too complicated to be productive in sophisticated apps. You don't need 'em.

Offline First

Nolan Lawson:

“If you design your UIs for people who are disconnected or only infrequently connected, you create better interfaces for everyone, including those who are online with fast connections.”

Brilliant post.

Greg Kick on Dagger 2

Dagger has always been a collaboration between Google and Square. Both companies are heavily invested in Guice (and Bob!), and eager to see our code become faster & easier to use.

Dagger 1.0 was born in Square Register for Android. We’d been using a lot of Guice, and had run into performance problems. Our goal was to build something that does fewer things and runs faster.

It worked. We built a simple runtime that worked with either reflection (for interactive development) and code-gen (for deployment).

Dagger 2 is being developed at Google. They're working in bigger code bases (web services!) and want something faster, particularly for graph building. So they've built something that does even fewer things and runs even faster.

Googlers Gregory Kick and Christian Gruber have done a fantastic job. The Dagger 2 generated code is so simple! For the full rundown, see Greg's talk, Dagger 2, A New Type of Dependency Injection. My favorite part is the auto principal for generating code:

  1. Constrain the problem.
  2. Generate the only reasonable implementation.

I'm eager for Dagger 2. Stab me plenty.

Nicer NPEs in Android L

KitKat + dalvikvm:

 java.lang.NullPointerException
  at com.roundsapp.HomeActivity.onCreate(HomeActivity.java:61)
  at android.app.Activity.performCreate(Activity.java:5312)

Android L + ART:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.ActionBar.setTitle(java.lang.CharSequence)' on a null object reference  
  at com.roundsapp.HomeActivity.onCreate(HomeActivity.java:61)
  at android.app.Activity.performCreate(Activity.java:5720)
  ...

I expect this to be extremely handy for those lines of code that involve chain several calls.

Why doesn't desktop Java have this?

Gson 2.3 and why you want it

When Gson binding fails, it gives you a crappy exception that tells you where in the document things went sideways:

com.google.gson.JsonSyntaxException: Expected a boolean but was NUMBER at line 1 column 4728  
    at com.google.gson.stream.JsonReader.nextBoolean()
    at com.google.gson.TypeAdapters$3.read()
    at com.google.gson.TypeAdapters$3.read()
    at com.google.gson.ReflectiveTypeAdapter$1.read()
    at com.google.gson.ReflectiveTypeAdapter$Adapter.read()
    at com.google.gson.ReflectiveTypeAdapter$Adapter.read()
    at com.google.gson.ReflectiveTypeAdapter$1.read()
    at com.google.gson.ReflectiveTypeAdapter$Adapter.read()
    ...

With Gson 2.3, you get a much nicer exception. It tells you the JSONPath to the failure. In this case, $.history[0].change_status.deletions:

com.google.gson.JsonSyntaxException: Expected a boolean but was NUMBER at line 1 column 4728 path $.history[0].change_status.deletions  
    at com.google.gson.stream.JsonReader.nextBoolean()
    at com.google.gson.TypeAdapters$3.read()
    at com.google.gson.TypeAdapters$3.read()
    at com.google.gson.ReflectiveTypeAdapter$1.read()
    at com.google.gson.ReflectiveTypeAdapter$Adapter.read()
    at com.google.gson.ReflectiveTypeAdapter$Adapter.read()
    at com.google.gson.ReflectiveTypeAdapter$1.read()
    at com.google.gson.ReflectiveTypeAdapter$Adapter.read()
    ...

Get Gson 2.3 from the

String Constants

Brent Simmons:

Here’s my secret, or maybe my superpower, or maybe just me being lucky — I’ve never had a bug related to using a string literal when I should have used a constant.

But I have had bugs when I used the wrong string constant.

I'm the same.

Holo vs. Material Design: Colors

Holo's color palette is opinionated, but limited. Five hues each in a primary and darker shade for a total of ten colors. (There's swatches for lighter tints, but these are rarely used.)

Material Design's color palette is the opposite: 19 hues, 16 of which have accent variants. With all tints including white and black, the palette is a neat 256 colors. With so many colors, Material Design is not a uniform, but a system. You might have six blue apps, with each one in a different shade of blue. The apps that use the system will be vibrant and colorful.

Both of my own apps (Shush & Rounds) use Holo's palette for a native look on Android 4.0. I didn't worry about colors: I just let the platform pick for me. Even Rounds’ icon uses the five Holo colors.

With Material Design in Android 5.0 (“The L Release”), I'm back in the driver’s seat. I'm okay with that. Though it might mean I'll need to redraw Rounds’ icon!

Comments should be sentences

Ned Batchelder:

Paying more attention to the comments will help you write better code. I can't tell you how many times I've written what I thought was a perfecty good function or line of code, then gone to write the comment or docstring, and realized a better way to do it, or even just a better name.

We follow this practice at Square and I'm very happy with it. Plus, if somebody forgets punctuation we get to joke, “You missed your period!” which is fun and silly.

Roboto, old and new

Today Google released a revised Roboto. Their design site says,

It is slightly wider and rounder, giving it greater clarity and making it more optimistic.

In Blue, Roboto from Android 4.4 (download .zip)
In Red, Roboto from “The L Release” (download .zip)

To my eyes they're quite a bit different. The new Roboto dots its i's and exclamation marks with circles; the old one with squares.

I'm not switching to FlatBuffers

On the Android Developers blog, Wouter van Oortmerssen writes:

Game developers, we've just released FlatBuffers, a C++ serialization library that allows you to read data without unpacking or allocating additional memory, as an open source project. [...] Use this library to store game data with less overhead than alternative solutions (e.g. Protocol Buffers or JSON).

The Java generated for FlatBuffers is ugly. For example, use the schema language to define an enum with flat buffers:

enum Color:byte { Red = 0, Green, Blue = 2 }  

That yields generated Java that isn't an enum!

public class Color {  
  public static final byte Red = 0;
  public static final byte Green = 1;
  public static final byte Blue = 2;
};

Worse, the format is not memory-safe. On Hacker News, Wouter writes:

Most readers of binary file formats can be made to read memory outside the buffer by corrupting the data, and FlatBuffers is no different.

That said, an option to bounds-check every offset would be possible, at a certain cost. Might be a nice optional feature to have.

Skipping bounds checks is what caused the Heartbleed bug. It's possible the Google servers using FlatBuffers may suffer the same problem!

FlatBuffers isn't ready. I'm going to stick with JSON

OkHttp ate MimeCraft

Last year, during Square's 7 days of open source, we announced Mime Craft, which makes it easy to build browser-style HTTP request bodies.

With this week's OkHttp 2 release candidate, we've promoted that MimeCraft code into OkHttp itself. You can encode a form request:

RequestBody formBody = new FormEncodingBuilder()  
  .add("search", "Jurassic Park")
  .build();
Request request = new Request.Builder()  
  .url("https://en.wikipedia.org/w/index.php")
  .post(formBody)
  .build();

Response response = client.newCall(request).execute();  

Or a multipart request:

RequestBody requestBody = new MultipartBuilder()  
  .type(MultipartBuilder.FORM)
  .addPart(
    Headers.of("Content-Disposition", "form-data; name=title"),
    RequestBody.create(null, "Logo"))
  .addPart(
    Headers.of("Content-Disposition", "form-data; name=image"),
    RequestBody.create(MEDIA_TYPE_PNG, new File("logo.png")))
  .build();

Request request = new Request.Builder()  
  .header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
  .url("https://api.imgur.com/3/image")
  .post(requestBody)
  .build();

Response response = client.newCall(request).execute();  

It's quite satisfying to build a multipart RequestBody from other RequestBody values. Yo dawg.

Complete examples are on the OkHttp recipes page.