WebView, addJavascriptInterface(), and Android 4.2 Change

TL;DR: Add @JavascriptInterface to any method you plan on exposing via addJavascriptInterface() in a WebView, to ensure long-term compatibility for your project.

The aforementioned change will be very important for apps whose android:targetSdkVersion is set to 17 or higher, running on Android 4.2+ devices. Methods without the @JavascriptInterface annotation will not be accessible from JavaScript.

This is for security reasons. Previously, any public method on the injected Java object would be reachable via JavaScript. Java classes usually have many inherited methods public methods, including ones like getClass(). JavaScript could then use reflection to access other stuff, beyond what you had in mind. By limiting access to @JavascriptInterface methods, only those you specifically opt into being accessible will be usable from the JavaScript environment.

The good news is that this improves security.

The bad news is that I missed hearing about this change, until this blog post showed up.

This change — a regression by some measures — was not mentioned in the Android 4.2 release notes. Also, the API differences report does not make this change obvious. Since the method signature for addJavascriptInterface() did not change, it does not show up in the report. While WebView itself does, the change in behavior is not mentioned in the class-level JavaDocs. Only if you read the documentation for the “un-modified” addJavascriptInterface(), or if you caught mention of the new JavascriptInterface annotation in the API differences report, would you have realized that this change was made.

Ideally, regressions like this would make it into the Android 4.2 release notes, as did the change in default ContentProvider exported status, the changes to user location accuracy, and the changes to some Settings.System read-write status, all of which were covered in the release notes.