Last active
July 29, 2024 08:32
-
-
Save pathnirvana/5f4c2ce100100dbc7f1cca58e877bbc0 to your computer and use it in GitHub Desktop.
Async Await call to JavascriptInterface Android Java WebView
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Allows to call a Android java function asynchronously | |
// spawn long running computations/io on the Java/Android without blocking the JS/Website running inside the WebView | |
// Eg. const result = await callAndroidAsync('javaFunction', { param1: 'value1', param2: 'value2' }) | |
// Please give a star if you find this useful | |
export async function callAndroidAsync(javaFuncName, params) { | |
const rand = 'asyncJava_' + Math.floor(Math.random() * 1000000) | |
window[rand] = {} | |
// func called from android | |
window[rand].callback = (isSuccess) => { | |
const dataOrErr = Android.runAsyncResult(rand) | |
if (isSuccess) window[rand].resolve(dataOrErr) | |
else window[rand].reject(dataOrErr) | |
delete window[rand] // clean up | |
} | |
// call some android function that returns immediately - should run in a new thread | |
// setTimeout(() => window[rand].callback(false, params.val * 2), 4000) // see testCallJavaAsync | |
Android.runAsync(rand, javaFuncName, JSON.stringify(params)) | |
return new Promise((resolve, reject) => { | |
window[rand].resolve = (data) => resolve(data) | |
window[rand].reject = (err) => reject(err) | |
}) | |
} | |
// async function testCallJavaAsync() { | |
// const res = await callJavaAsync('testFunc', { val: 100 }) | |
// console.log(`received res = ${res}`) | |
// } | |
// testCallJavaAsync() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class WebAppInterface { | |
WebView webView; | |
Map<String, String> runAsyncResults = new ConcurrentHashMap<>(); | |
WebAppInterface(WebView wv) { | |
webView = wv; | |
} | |
@JavascriptInterface | |
public void runAsync(final String rand, final String funcName, final String jsonParams) { | |
final WebAppInterface wai = this; | |
new Thread() { | |
// runs the java function in a new thread | |
@Override public void run() { | |
try { | |
final JSONObject params = new JSONObject(jsonParams); | |
String result = (String) wai.getClass().getMethod(funcName, JSONObject.class).invoke(wai, params); | |
wai.jsResolve(rand, true, result); | |
} catch (InvocationTargetException ite) { // exceptions inside the funcName function | |
wai.jsResolve(rand, false, ite.getCause().toString()); | |
} catch (Exception e) { | |
wai.jsResolve(rand, false, e.toString()); | |
} | |
} | |
}.start(); | |
} | |
private void jsResolve(String rand, boolean isSuccess, String result) { // notify that result is ready | |
runAsyncResults.put(rand, result); | |
final String url = "javascript:" + rand + ".callback(" + isSuccess + ")"; | |
Log.i("LOG_TAG", "calling js method with url " + url); | |
webView.post(new Runnable() { | |
@Override | |
public void run() { | |
webView.loadUrl(url); | |
} | |
}); | |
} | |
@JavascriptInterface | |
public String runAsyncResult(String rand) { // returns the result from runAsync to JS | |
String result = runAsyncResults.get(rand); | |
runAsyncResults.remove(rand); | |
return result; | |
} | |
// Java functions that you need to be called from Javascript needs to be declared here as Public functions | |
// e.g. public String javaFunction(JSONObject params) { ... } | |
} |
Thanks for sharing your codes.
I simplified your logic to work with androidx WorkManager.
https://gist.github.com/EaseTheWorld/12f73e1d1466d8d570f36b3e49e79a39
Basically idea is same except
- Use own namespace instead of window['xxx']
- requestId(='rand') will be created in Android side.
- pass callback directly to android so js part can have control of the callback function name.
- result is not saved in map because WorkManager handles it.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Allows to call a Android java function asynchronously
spawn long running computations/io on the Java/Android without blocking the JS/Website running inside the WebView
E.g. call from JS inside Webview
const result = await callAndroidAsync('javaFunction', { param1: 'value1', param2: 'value2' })
definition of the function in Java/Android
public String javaFunction(JSONObject params) { ... }
Please give a star if you find this useful