Skip to content

Instantly share code, notes, and snippets.

@EaseTheWorld
Last active October 26, 2022 05:29
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EaseTheWorld/12f73e1d1466d8d570f36b3e49e79a39 to your computer and use it in GitHub Desktop.
Save EaseTheWorld/12f73e1d1466d8d570f36b3e49e79a39 to your computer and use it in GitHub Desktop.
Simple implementation of AndroidPromise(Run android async work from javascript using ES6 Promise/async/await)
var AndroidPromise = {
callbacks: {},
requestId: 0,
request: function (work, params={}) {
return new Promise((resolve, reject) => {
let requestId = this.requestId++
this.callbacks[requestId] = {
'resolve': resolve,
'reject': reject
}
AndroidAsyncRequest.request(work, JSON.stringify(params),
'AndroidPromise.onResolve('+requestId+')',
'AndroidPromise.onReject('+requestId+')'
)
})
},
onResolve: function (requestId) {
let callback = this.callbacks[requestId].resolve
delete this.callbacks[requestId]
return callback
},
onReject: function (requestId) {
let callback = this.callbacks[requestId].reject
delete this.callbacks[requestId]
return callback
}
}
fun interface AsyncRequest {
fun request(workId: String, params: String, successCallback: Callback, failCallback: Callback)
fun interface Callback {
fun onResult(result: String)
}
}
class AsyncRequestJavascriptInterface(private val delegate: Delegate) {
@JavascriptInterface
fun request(workId: String, params: String, successJsCallback: String, failJsCallback: String) {
return delegate.request(workId, params, successJsCallback, failJsCallback)
}
companion object {
const val JAVASCRIPT_INTERFACE_NAME = "AndroidAsyncRequest"
}
fun interface Delegate {
fun request(workId: String, params: String, successJsCallback: String, failJsCallback: String)
}
}
@SuppressLint("SetJavaScriptEnabled")
class AsyncWebView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
): WebView(context, attrs) {
init {
settings.javaScriptEnabled = true
}
fun setWorkRequestProvider(asyncRequest: AsyncRequest) {
addJavascriptInterface(createAsyncRequestJavascriptInterface(asyncRequest),
AsyncRequestJavascriptInterface.JAVASCRIPT_INTERFACE_NAME)
}
private fun createAsyncRequestJavascriptInterface(asyncRequest: AsyncRequest) =
AsyncRequestJavascriptInterface { workId, params, successJsCallback, failJsCallback ->
val successCallback = AsyncRequest.Callback {
evaluateJavascript("$successJsCallback('$it')", null)
}
val failCallback = AsyncRequest.Callback {
evaluateJavascript("$failJsCallback('$it')", null)
}
post {
asyncRequest.request(workId, params, successCallback, failCallback)
}
}
}
<!DOCTYPE html>
<html>
<head>
<script src="file:///android_asset/AndroidPromise.js"></script>
</head>
<body>
<script>
function printStatus(s) {
let d = new Date()
let line = "<br>" + d.getHours()+":"+d.getMinutes()+":"+d.getSeconds() + " " + s
document.getElementById('status').innerHTML += line
}
async function test1(work, params) {
printStatus(work + " start ("+params+")")
let response = await AndroidPromise.request(work, params)
printStatus(work + " end ("+response+")")
}
</script>
<div onclick="test1('work1', 3000).then(function(){console.log('after test1')})">
<p>work1</p>
</div>
<div onclick="test1('work2', 5000)">
<p>work2</p>
</div>
<div id="status">
<hr>
</div>
</body>
</html>
@EaseTheWorld
Copy link
Author

EaseTheWorld commented Apr 13, 2022

I created this to call androidx Work from js side but generally it can be used for any android async work with string-identifier.
Running order is like below.

  1. [JS] AndroidAsyncWork.request
  2. [Android] requestAsyncWork
  3. [JS] onResponse

Basic idea is same as https://gist.github.com/pathnirvana/5f4c2ce100100dbc7f1cca58e877bbc0

@andycandy-de
Copy link

Hello :-)
I also had some trouble to implement a javascript interface with the android SDK. Based on the idea in the gist you referenced in your comment I created a SimpleAndroidBridge which allows you to build an easy interface between android(kotlin) and webview(java) with a full promise support.
Just check it out and let me now what you think about it :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment