Android JNI runtime primitives and MoonBit lifecycle bridge.
moon add Nanaloveyuki/ajniimport {
"Nanaloveyuki/ajni/webview",
}let string = try! @ajni.JniClass::parse("java/lang/String")
let signature = try! @ajni.JniMethod::new(
[@ajni.JniType::object(string)],
return_type=@ajni.JniType::boolean(),
)
let registration = try! @ajni.NativeMethod::new("nativeAcceptsString", signature)
println(registration.descriptor()) // (Ljava/lang/String;)Zimport {
"Nanaloveyuki/ajni/android",
}
let subscription = @android.install_event_handler(event => match event {
@android.AndroidEvent::Lifecycle(@android.Lifecycle::Resumed) => println("resumed")
@android.AndroidEvent::UiTask => println("Android main Looper callback")
_ => ()
})
// Remove the observer before application shutdown.
@android.remove_event_handler(subscription)import dev.nanaloveyuki.ajni.host.NativeBridge
NativeBridge.initialize(applicationContext)
NativeBridge.attachWebViewContainer(container)
// Forward every Activity lifecycle state on the main thread.
NativeBridge.lifecycle(state)
// During Activity teardown:
NativeBridge.detachWebViewContainer(container)
NativeBridge.shutdown()import {
"Nanaloveyuki/ajni/webview",
}
let subscription = @webview.install_event_handler(event => match event.kind {
@webview.EventKind::Created(_) => println("ready")
@webview.EventKind::ScriptResult(request_id, json) =>
println("\{request_id}: \{json}")
@webview.EventKind::PageMessage(body, origin, _is_main_frame) =>
println("\{origin}: \{body}")
@webview.EventKind::AssetRequest(request) => println(request.path)
@webview.EventKind::OperationFailed(operation_id, message) =>
println("\{operation_id}: \{message}")
_ => ()
})
try! @webview.create(
1L,
"https://app.example.test",
@webview.InitialContent::Url("https://app.example.test/assets/index.html"),
document_start_scripts=["globalThis.appReady = true"],
operation_id="create-browser",
)
try! @webview.eval(1L, "document.title", "title-request")
try! @webview.destroy(1L, operation_id="destroy-browser")
@webview.remove_event_handler(subscription)moon fmt --check
moon check --target native
moon test --target native -v$env:ANDROID_SDK_ROOT = "C:\path\to\Android\Sdk"
$env:ANDROID_NDK_HOME = "C:\path\to\android-ndk-r29"
$env:ANDROID_SERIAL = "emulator-5554"
gradle -p android :app:connectedDebugAndroidTest///|
test {
let string = try! JniClass::parse("java/lang/String")
let signature = try! JniMethod::new(
[JniType::object(string)],
return_type=JniType::boolean(),
)
let registration = try! NativeMethod::new("nativeAcceptsString", signature)
assert_eq(registration.descriptor(), "(Ljava/lang/String;)Z")
}pub(all) suberror JniError {
NotInitialized
RuntimeDestroyed
NativeFailure(String)
JavaException(String)
InvalidClassName(String)
InvalidNativeMethodName(String)
DescriptorTooLong
TooManyParameterSlots
TooManyArrayDimensions
} derive(Debug)fn decode_utf8(bytes : BytesView) -> StringAndroid JNI runtime primitives and MoonBit lifecycle bridge.