6. JS_Object
JavaScript
-‐>
Java
public class WebAppInterface {
Context mContext;
/** Instantiate the interface and set the context */
WebAppInterface(Context c) {
mContext = c;
}
/** Show a toast from the web page */
@JavascriptInterface
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
}
}
Let’s
build
an
interface:
7. JS_Object
JavaScript
-‐>
Java
JS WebView
Quite
good
performance
Use
native
bridging
suggested
by
Google
Error
prone
<script type="text/javascript">
function showAndroidToast(toast) {
Android.showToast(toast);
}
</script>
WebSettings settings =
webView.getSettings();
settings.setJavaScriptEnabled(true);
webView.addJavascriptInterface(new
WebAppInterface(this), "Android");
8. Prompt
JavaScript
-‐>
Java
JS WebChromeClient
Doesn’t
crash
the
emulator
It’s
very
slow
Overrides
default
prompt
behaviour
in
WebView
Criticised
as
antipattern
<script type="text/javascript">
prompt("toast", "This is Toast message");
</script> @Override
public boolean onJsPrompt (WebView view, String
url, String message, String defaultValue,
JsPromptResult result) {
// message determines action
if(message == "toast") {
// make toast ...
}
}
9. loadUrl()
Java
-‐>
JavaScript
Native JS
Quite
fast
Breaks
inputs
behaviour
<script type="text/javascript">
onLocationUpdate(int lat, int lng) {
alert("Success: lat=" + lat + " lng: " + lng);
}
</script>
@Override
public void onLocationChanged(Location
location) {
String lat =
Double.toString(location.getLatitude());
String lng =
Double.toString(location.getLongitude());
webView.loadUrl("javascript:onLocationUpda
te(" + lat + "," + lng + ");");
}
10. Online
Event
Java
-‐>
JavaScript
Native JS
It’s
fast
Even
faster
than
loadUrl()
Doesn’t
break
anything
(yet)
Problem
in
case
of
bridging
more
than
one
WebView
<script type="text/javascript">
var handleEvent = function() {
// get result from native code
// using exposed interface
}
window.addEventListener("online", handleEvent);
window.addEventListener("offline", handleEvent);
</script>
boolean flipFlop;
// (...)
@Override
public void informJavaScriptAboutResult() {
flipFlop = !flipFlop;
webView.setNetworkAvailable(flipFlop);
}
11. Private
API
Java
-‐>
JavaScript
Class webViewClass = WebView.class;
try {
Field f = webViewClass.getDeclaredField("mProvider");
f.setAccessible(true);
webViewObject = f.get(webView);
webViewClass = webViewObject.getClass();
} catch (Throwable e) {
// ...
}
try {
Field f = webViewClass.getDeclaredField("mWebViewCore");
f.setAccessible(true);
webViewCore = f.get(webViewObject);
if (webViewCore != null) {
sendMessageMethod = webViewCore.getClass().getDeclaredMethod("sendMessage", Message.class);
sendMessageMethod.setAccessible(true);
}
} catch (Throwable e) {
// ...
}
Be
careful
while
using
reflection…
12. Private
API
Java
-‐>
JavaScript
Native JS
Super
fast
Not
supported
officially
Works
on
Android
3.2+
May
break
in
the
future
<script type="text/javascript">
onLocationUpdate(int lat, int lng) {
alert("Success: lat=" + lat + " lng: " + lng);
}
</script>
try {
String js = "onLocationUpdate(" +
lat + "," + lng + ");";
Message execJsMessage =
Message.obtain(null, EXECUTE_JS, js);
sendMessageMethod.invoke(webViewCore,
execJsMessage);
} catch (Throwable e) {
// ...
}