Closed bangonkali closed 4 years ago
My mistake. I forgot that this is a JSONObject
and not a JSObject
.
Ok, the less simple way of getting it (sorry, in Java -- my Kotlin knowledge is not great):
Put this in your ServiceStartListener
:
class ContextBean {
JSContext context;
}
final ContextBean contextBean = new ContextBean();
service.getProcess().addEventListener(new Process.EventListener() {
@Override
public void onProcessStart(final Process process, final JSContext context) {
// ^^^^^^^^^^^^^^^^^
// HERE IS THE CONTEXT
contextBean.context = context;
}
@Override public void onProcessExit(Process process, int exitCode) {}
@Override public void onProcessAboutToExit(Process process, int exitCode) {}
@Override public void onProcessFailed(Process process, Exception error) {}
});
final JSContext context = contextBean.context;
Now you have the context.
Some notes.
ContextBean
class is necessary to deal with the fact we are accessing the context from an inner class, so it needs to be declared final
. Maybe Kotlin has a better way of dealing with this.ServiceStartListener
, it is guaranteed to be synchronous because (1) the service has already started, and (2) the start listener is always called from the process thread (see JavaDoc -- this is the important bit: "In the event that an EventListener is added by Process.addEventListener() after a process has already started, this method will be called immediately (in the process thread) if the process is still active."). ServiceStartListener
, it is not guaranteed to be synchronous, so the last line (final JSContext context = contextBean.context;
) might be null
. But if you do this inside the start listener only, this should work.Thanks for the example @ericwlange!
I was able to make it work using the following:
// ...more code...
val processEventListener = object : Process.EventListener {
override fun onProcessAboutToExit(process: Process?, exitCode: Int) {}
override fun onProcessExit(process: Process?, exitCode: Int) {}
override fun onProcessFailed(process: Process?, error: Exception?) {}
override fun onProcessStart(process: Process?, context: JSContext?) {
if (context != null) {
jsContext = context
context.evaluateScript("var versions = JSON.stringify(process.versions);")
val versions = context.property("versions")
Log.d(TAG, "Javascript context retrieved. $versions")
}
}
}
// ...more code...
val startListener =
ServiceStartListener { service ->
Log.d(TAG, "Microservice started.")
service.process.addEventListener(processEventListener)
...more code...
}
// ...more code...
microService = MicroService(
context,
res,
startListener
)
Output for Log.d(TAG, "Javascript context retrieved. $versions")
, related to #137:
> Javascript context retrieved. {"http_parser":"2.7.0","node":"8.9.3","v8":"6.1.534.48","uv":"1.15.0","zlib":"1.2.11","ares":"1.10.1-DEV","modules":"57","nghttp2":"1.25.0","openssl":"1.0.2n","liquidcore":"0.6.2"}
Full wrapper for reference:
package my.package.name.service
import android.util.Base64
import android.util.Log
import org.json.JSONObject
import org.liquidplayer.javascript.JSContext
import org.liquidplayer.node.Process
import org.liquidplayer.service.MicroService
import org.liquidplayer.service.MicroService.EventListener
import org.liquidplayer.service.MicroService.ServiceStartListener
import my.package.name.R
import java.io.InputStream
import java.lang.Exception
import java.net.URI
class MyMicroservice(private val context: MyService) {
companion object {
private const val TAG: String = "MyMicroservice"
}
private lateinit var microService: MicroService
private lateinit var jsContext: JSContext
fun init() {
val res = URI("android.resource://my.package.name/raw/index")
val wasmStream: InputStream = context.resources.openRawResource(R.raw.main)
val wasmBytes: ByteArray = wasmStream.readBytes()
val wasmBase64 = Base64.encodeToString(
wasmBytes,
Base64.DEFAULT or Base64.NO_WRAP
)
Log.d(TAG, "Wasm Loaded (Base 64): $wasmBase64")
val processEventListener = object : Process.EventListener {
override fun onProcessAboutToExit(process: Process?, exitCode: Int) {
TODO("not implemented")
}
override fun onProcessExit(process: Process?, exitCode: Int) {
TODO("not implemented")
}
override fun onProcessFailed(process: Process?, error: Exception?) {
TODO("not implemented")
}
override fun onProcessStart(process: Process?, context: JSContext?) {
if (context != null) {
jsContext = context
context.evaluateScript("var versions = JSON.stringify(process.versions);")
val versions = context.property("versions")
Log.d(TAG, "Javascript context retrieved. $versions")
}
}
}
val exitListener =
EventListener { service, event, payload ->
Log.d(TAG, "Event:$event ${payload.getString("message")}")
context.state = MyService.STOPPED
context.terminateService()
}
val logListener =
EventListener { service, event, payload ->
Log.d(TAG, "Event:$event ${payload.getString("message")}")
}
val readyListener =
EventListener { service, event, payload ->
Log.d(TAG, "Event:$event")
service.emit("req_init", wasmBase64)
}
val initListener =
EventListener { service, event, payload ->
Log.d(TAG, "Event:$event ${payload.getString("message")}")
}
val startListener =
ServiceStartListener { service ->
Log.d(TAG, "Microservice started.")
service.process.addEventListener(processEventListener)
service.addEventListener("log", logListener)
service.addEventListener("res_ready", readyListener)
service.addEventListener("res_init", initListener)
service.addEventListener("res_exit", exitListener)
context.state = MyService.STARTED
}
microService = MicroService(
context,
res,
startListener
)
}
fun stop() {
Log.d(TAG, "Stopping My microservice.")
microService.emit("req_exit")
}
fun start() {
Log.d(TAG, "Starting My microservice.")
microService.start()
}
}
After much contemplation about this, I think using context might not be the best approach at all for my needs 😂 but nonetheless thanks for guiding me in this respect.
Using
'com.github.LiquidPlayer:LiquidCore:0.6.2'
I could not getpayload.getContext()
fromEventListener
using Kotlin 1.3.60.Related to https://github.com/LiquidPlayer/LiquidCore/issues/138#issuecomment-558239276