The CommonsBlog


The Busy Coder's Guide to Android Development Version 8.3 Released

Subscribers now have access to the latest release of The Busy Coder’s Guide to Android Development, known as Version 8.3, in all formats. Just log into your Warescription page and download away, or set up an account and subscribe!

This is a fairly small update, in which I:

  • Added a chapter on Android Things

  • Fixed some flaws in the chapter on RxJava

  • Added material on using “transcript mode” to the chapter on advanced RecyclerView techniques

  • Revised the coverage of integrating Java and JavaScript in the chapter on advanced WebView techniques, including adding material on using WebMessage and WebMessagePort

  • Updated the chapter on the Design Support Library, showing how to use the CWAC-CrossPort edition of those widgets with Theme.Material, rather than using the Design Support Library and having to use appcompat-v7

  • Changed a bunch of sample apps to switch from using onPause() and onResume() to using onStop() and onStart(), to be friendlier to multi-window environments

  • Made various miscellaneous improvements and errata fixes

The next book update should be no later than early April. The timing depends in large part on if Google ships something significant (Android Studio 2.3? Android 7.2? O Developer Preview? Android for Datacenters?!? Google Knit?!?!?) that I need to cover quickly.

Feb 13, 2017


Analytics Privacy Survey

The Guardian Project, as part of The Berkman-Klein Assembly, is conducting a survey about mobile app analytics. They are concerned about the privacy issues involving analytics and are using this survey to gauge developer opinion on the subject. It’s a short eight-question survey (though all fields are mandatory, for some reason…). If you have five minutes to spare, hop over to the survey and fill it out.

Feb 01, 2017


Android Studio and the Case of the Rogue Parentheses

TL;DR: Follow bug report instructions in the order they are presented, as order may impact your ability to reproduce the bug.

Android Studio 2.2.x has a bug (also reported here and here). If you do things in a specific sequence, you will wind up in a state where the Properties pane of the GUI editor will generate buggy layout XML.

The catch is that the sequence of events matters.

When I first tried to reproduce the bug, I did this:

  • Created a scrap project

  • Dragged a Button into my activity’s layout

  • Added the method to my activity that I wanted to use with android:onClick

  • Attempted to set the android:onClick attribute via the drop-down list in the Properties pane

This sequence illustrates a different bug — the drop-down does not include my method — but it does not reproduce the specific reported issue.

This sequence of events, though, reproduces it nicely:

  • Created a scrap project

  • Added the method to my activity that I wanted to use with android:onClick

  • Dragged a Button into my activity’s layout

  • Attempted to set the android:onClick attribute via the drop-down list in the Properties pane

There, the drop-down list will contain the activity name in parentheses, after the method name. So, if your activity is MainActivity and your method is foo(), the drop-down list has foo (MainActivity). If you choose it, you wind up with android:onClick="foo (MainActivity)". That is invalid syntax, as android:onClick only takes the name of the method. As a result, you crash when clicking the Button, because Android cannot find a method with the name foo (MainActivity), in part because that is not a legal method name.

Fortunately, Ravikumar N managed to set me straight.

Ideally, Lint would have caught this, on the ground that android:onClick should only have something that could be a valid Java method name (or a data binding expression). I filed a feature request for that Lint check.

But, the moral of this story is: follow bug-reproduction instructions to the letter, as best you can. In my case, I assumed that the order of creating the Button and adding the method did not matter, and that was an invalid assumption.

Jan 31, 2017


Network Security Configuration Presentation

If you are in the Greater Reigning Super Bowl Champions For Another Few Days Metropolitan Area (or “Denver”, for short), I’ll be delivering a presentation on Android’s network security configuration system by remote to the Denver Droids group on February 15th. I will cover:

  • What network security configuration is

  • How you use it to solve some common SSL problems

  • How you use it to enhance your security beyond ordinary SSL, and

  • How to deal with one itty-bitty problem: network security configuration is new to Android 7.0

Reportedly, refreshments will be served, though since I will not be there in person, I will not be able to confirm this. I might have refreshments in my Secret Mountain Lair, but, well, that’s a secret.

If you have an Android developer group, and would like me to deliver a presentation for your group, just ask!

Jan 30, 2017


Replacing addJavascriptInterface() with HTML Message Channels

One item in Google’s app security checklist caught my eye late last week:

WebViews do not use addJavaScriptInterface() with untrusted content.

On Android M and above, HTML message channels can be used instead.

I had glossed over HTML message channels back in my Android 6.0 “random musings” post, and I was somewhat at a loss as to how to use them to replace addJavascriptInterface().

Fortunately, Diego Torres Milano came to my rescue, pointing out a CTS test case for these APIs. From there, I was able to figure out how this stuff works, more or less.

The classic ways we have used to bridge Java and JavaScript, in the context of a WebView, are:

  • loadUrl("javascript:...") and evaluateJavascript(), to have Java invoke JavaScript code

  • addJavascriptInterface() to expose a Java object as a notional JavaScript global, so that JavaScript can call methods exposed on that object

The latter has been the source of many security bugs over the years, which presumably is why Google is counseling against it.

HTML message channels are a viable alternative, for cases where you control the Web content being shown in the WebView.

postWebMessage() is a method on WebView that allows you to send over an arbitrary string to the JavaScript code in the currently loaded Web page. To receive it, though, the JavaScript must have registered a global onmessage function. So, postWebMessage(new WebMessage("Hi"), ...) will cause the following onmessage function to be called, with e.data being "Hi":

onmessage = function (e) {
  parse(e.data);
}

This can serve as a replacement for loadUrl() and evaluateJavascript(), for Java telling the JavaScript in the current Web page to do something… if and only if the JavaScript is set up to listen to those messages.

Replacing addJavascriptInterface() is substantially more involved, including:

  • Calling createWebMessageChannel() on the WebView, to get a WebMessagePort pair representing a communications channel

  • Passing one of those ports to JavaScript via postWebMessage()

  • Each side, as needed, registering handlers to listen for messages on those ports

  • Each side, as needed, sending messages to the other side via those ports

My Stack Overflow answer has a bit more detail. This sample app shows it in use, and I’ll be covering this in greater detail in the next update to The Busy Coder’s Guide to Android Development.

There are some limitations, though:

  • You have to modify the JavaScript code to work with these message ports, which should not be a huge issue, given that you had to modify the JavaScript to talk to your injected notional JavaScript global from addJavascriptInterface()

  • A bug or undocumented limitation requires you to use loadDataWithBaseURL() and an http or https URL to make this work. You cannot, for example, use this with loadUrl("file:///android_asset/..."), which confused the heck out of me when I was trying to go that route in the sample app.

  • This is only available on Android 6.0+, which means until your minSdkVersion is 23 or higher, you have to use the other APIs as well, at least for the older devices that you are supporting.

Is this more secure than addJavascriptInterface()? Probably, insofar as the scope of the API that you expose from Java to the JavaScript code is more intentional. It is more difficult to accidentally expose something when it is more difficult for you to expose anything. However, neither HTML message channels nor addJavascriptInterface() are great solutions for when you are working with arbitrary HTML/JS that you did not write.

Jan 23, 2017


Older Posts