Android – javascript Bridge/Interface

Hey friends, Recently come across a requirement for communicating from the Web back to the app. Normally, if app will look for loading URL using shouldOverrideUrlLoading(). so app will perform certain operation specific to the url for example setting a title for particular url loaded in web content. But if the web decides which title string to be shown, then app has to listen to web using javascript interface or simply called as JSbridge.

To create a webview in your activity you need to add the webView widget to the layout.

<?xml version="1.0" encoding="utf-8"?>
<WebView  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
/>

To load a web page in the WebView, use loadUrl(). For example:

WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("http://www.example.com");

Note: Ensure you have added the internet permission in your androidManifest file.

To make the javascript enabled for the webview, enable the JS setting as true.

webSettings.setJavaScriptEnabled(true);

Binding JavaScript code to Android code

To bind a new interface between your JavaScript and Android code, call addJavascriptInterface(), passing it a class instance to bind to your JavaScript and an interface name that your JavaScript can call to access the class.

For example, you can include the following class in your Android application:

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 title) {
        Toast.makeText(mContext, title, Toast.LENGTH_SHORT).show();
    }
}

Caution: If you’ve set your targetSdkVersion to 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available to your JavaScript (the method must also be public). If you do not provide the annotation, the method is not accessible by your web page when running on Android 4.2 or higher.

You can bind this class to the JavaScript that runs in your WebView with addJavascriptInterface() and name the interface Android. For example:

WebView webView = (WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new WebAppInterface(this), "Android");

On the Web side, Android Interface showToast is visible and all you need to call the function in the script tag.

<input type="button" value="Say hello" 
onClick="showAndroidToast('Hello Android!')" />

 type="text/javascript">
    function showAndroidTitle(title) {
        Android.showToast(title);
    }


IMPORTANT: only primitive data types are supported to passed 
across the JS and android app. if you try passing say for example 
JSONObject or Object, it will be null as these datatypes are not 
supported.

But workaround can be achieved by passing all the jsoninfo as strings 
and the app has to parse it to JSONObject.

JsonObject jsonObject = (JsonObject) jsonParser.parse(jsonstring);

All good. App will show the Title string info to be passed. Happy coding 🙂

Advertisement

Roboguice – Best dependancy Injection framework

Instead of creating dependancies on your own, use the third party or framework to do your job.

DI is used to move the responsibility of creating an object outside the main code and  give you back the reference to be used in your code. So very less from your end and DI has to handle it. So how to achieve this in android. we have lot of third party frameworks such as ButterKnife, Dagger 2, Android Annotations, Roboguice. These are popular DI framework libs used by most android developers. I have used Roboguide 3.0 for my project and quite appreciate the use of Roboguice DI framework.

Basically, Ideas being the DI is to avoid your class create objects on its own. instead get the object passed so you avoid tight coupling of your app.

Screen Shot 2016-05-12 at 2.15.16 pm

Voila!!…no need to do findViewByID everytime to load the widget. your code looks clean and neat.

for more info, refer Roboguice Wiki

Happy Coding 🙂