1

Hello i am creating a Android Application. I do not like using Androids UI System and have elected to use the WebView for UI Design as it is easier for me coming from a HTML5 Background. I have tried platforms like Cordova and Phonegap but they dont give me exactly the control id like as i also have a Java background. So just to reiterate i am using the WebView for UI only.

That being said there is a small amount of JavaScript code i would like to run on the web view, namely, Network Calls. I have a network back-end using OkHttp and can make those connections fine! But i cannot get any data back in a way that would be friendly to my current knowledge of webview.

Here is my JavaScript function signature:

function makeRequest(method,url,data,callback){
    ... Code Here ...
}

And I would like to call it like this:

makeRequest("GET","http://www.example.com/",{
    "key1" : "value1",
    "key2" : "value2"
},(code,responseJSON) => {
    ... Handle Response...
});

So far on my Android/Java side i have this:

@JavascriptInterface
public void makeRequest(String method, String url, String data, ??? callback){
    ... Handle Request Java-side ...
}

When the request is handled id like to call the callback function some how. Like an EventListener or something, but i am stumped as to the Type '???' Should be, or how i would go about calling that function so that the JavaScript code can receive its callback and continue.

I already have One-Way code working through my JavaScriptInterface with webview. and JSON is no problem, as its converted to a string in the JS code, and GSON can parse and get what i need. Its just this callback that has me stumped!

Thank you in advance for any help :)

2 Answers2

1

You can do it like this,

public class MyJavaScriptInterface {
    private final MyJavaScriptInterfaceCallBack myJavaScriptInterfaceCallBack;

    public interface  MyJavaScriptInterfaceCallBack{
        void clickedAdmission(YourDataType code,String responseJSON);
    }
    public MyJavaScriptInterface(MyJavaScriptInterfaceCallBack myJavaScriptInterfaceCallBack) {
        this.myJavaScriptInterfaceCallBack=myJavaScriptInterfaceCallBack;
    }

    @JavascriptInterface
    public void applynow() {
        myJavaScriptInterfaceCallBack.clickedAdmission();
    }

}

Then in your fragment of activity

where your fragment or activity must implement the MyJavaScriptInterface.MyJavaScriptInterfaceCallBack interface and the method.

Set javascript interface in WebView

webView.addJavascriptInterface(new MyJavaScriptInterface(this), "YourRecognizer");
rahat
  • 1,489
  • 5
  • 14
  • This is still One Way, as in calling ``` window.YourRecognizer.applynow() ``` is how you would reach this code. Im Trying to call like this: WebView JS Code (with callback) -> Java Code -> WebView JS Code Callback. I think its best described as passing a funtion to be called at a later time when an Asynchronous Task is complete, and notifying the WebView/JS Function that the process is complete by calling a function supplied as an argument aka a CallBack. It looks like this may not be totally supported! – Draven Lewis Jan 20 '21 at 14:22
  • [This](https://stackoverflow.com/questions/4325639/android-calling-javascript-functions-in-webview) can help you – rahat Jan 20 '21 at 14:57
0

Okay it seems the intended behavior is impossible, but with API 21+ you have access to the Webview#postMessage() Method to talk back and forth between the Runtimes. here is basically what i did:

JavaScript Code

function makeHTTPRequest(method,url,data,callback){
    // may have to do a check on data
    var number = Math.floor(Math.random() * 1000);
    window.host.makeHTTPRequest(number,method,url,JSON.stringify(data));
    window.addEventListener("message",(ev) => {
        var JSONData = JSON.parse(ev.data);
        if(JSONData.id == number){
            callback(JSONData.code,JSONData.payload.data);
        }
    });
}

Java Code

@JavascriptInterface
public void makeHTTPRequest(int id, String method, String url, String data){
    createRequest(id, method, url, data, new MethodCallBackInterface() {
        @Override
        public void done(String message) {
            parent.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    view.postWebMessage(new WebMessage(message), Uri.parse("*"));
                }
            });
        }
    });
}

The ID is important! When calling the method, we must generate an ID, that id sent to the main Java Application and included in the final JSON code that is then send back to the JS code. Can be checked, if equal, then we can call our callback. Usage of threads on the Java side, ensure the Async nature i was going for, while keeping the callback on the JS side.

This method works the same way as communicating between IFrames in HTML. So if we treat our Android Application and out Web Application the same as Sand-boxed IFrames we can communicate the same way.