Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call Android method from TypeScript

Android injects a JS interface into a web view:

JavaScriptInterface javaScriptInterface = new JavaScriptInterface(this);
browser.addJavascriptInterface(javaScriptInterface, "qp");

The interface looks like this:

public class JavaScriptInterface {

    private ILoadEpi iLoadEpi;

    public JavaScriptInterface(ILoadEpi iLoadEpi) {
        this.iLoadEpi = iLoadEpi;
    }

    @JavascriptInterface
    public void passParameters(String fldMerchCode,
                               String fldMerchRefNbr,
                               String fldTxnAmt,
                               String fldTxnScAmt,
                               String fldDatTimeTxn,
                               String fldDate1,
                               String fldDate2
                               ) {
        Log.d("fldMerchCode", fldMerchCode);
        Log.d("fldMerchRefNbr", fldMerchRefNbr);
        Log.d("fldTxnAmt", fldTxnAmt);
        Log.d("fldTxnScAmt", fldTxnScAmt);
        Log.d("fldDatTimeTxn", fldDatTimeTxn);
        Log.d("fldDate1", fldDate1);
        Log.d("fldDate2", fldDate2);
        iLoadEpi.loadEpi(fldMerchCode, fldMerchRefNbr, fldTxnAmt, fldTxnScAmt, fldDatTimeTxn, fldDate1, fldDate2);
    }
}

How can a web app developed using TypeScript call this Android?

Or more broadly, how can a TypeScript application call an Android method?

like image 555
Sandah Aung Avatar asked Jan 05 '23 21:01

Sandah Aung


1 Answers

Add a TypeScript definition for the JavaScriptInterface type that will be injected by Android. Then declare a variable with the name of the instance injected by Android, then use it as normal. In your example, the definition you need is:

interface JavaScriptInterface {
    passParameters(fldMerchCode: string,
                   fldMerchRefNbr: string,
                   fldTxnAmt: string,
                   fldTxnScAmt: string,
                   fldDatTimeTxn: string,
                   fldDate1: string,
                   fldDate2: string) : void;
}

declare var qp: JavaScriptInterface;

The qp instance injected by Android will have the method passParameters available on it. The instance is created by Android with the name qp in your call to browser.addJavaScriptInterface(javaScriptInterface, "qp");. Note that, depending on how your passParameters function is used, you may need to declare the return type as any instead of void.

Here's a complete example based on the Android guide for binding JS:

In your HTML file, add:

<input type="button" value="Say hello" id ="button"/>
<script src="./generated/bundle.js"></script>

where I assume that your generated/transpiled JavaScript is located at ./generated/bundle.js, relative to the HTML file.

In your TypeScript file, add:

interface WebAppInterface {
    showToast(toast: string) : any;
}

declare var android: WebAppInterface;

var button = document.getElementById('button');
button.onclick = ()=>android.showToast('Hello Android!');

Note that the linked Android example names the injected object android:

webView.addJavascriptInterface(new WebAppInterface(this), "android");

And in case the linked example changes or disappears, here is the example WebAppInterface.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();
    }
}
like image 64
Malina Avatar answered Jan 13 '23 08:01

Malina