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.