本記事に誤りを見つけた場合は,コメントにて優しく教えていただけると助かります
はじめに
自作プラグインを作成すると Kotlin を使用できるようになります.
このとき,Kotlin からチャンネルでデータを送信する場合,少しトリッキーな実装をする必要があるらしいです.
そんな実装方法について紹介します
プラグインのセットアップまでは↓を参照してください
Kotlin
コマンドを介して Channel を受け取るようにします
tauri-plugin-test/android/src/main/java/ExamplePlugin.kt
import app.tauri.plugin.Channel
@InvokeArg
class SetEventHandlerArgs {
lateinit var handler: Channel
}
class ExamplePlugin() {
var channel: Channel? = null
@Command
fun setEventHandler(invoke: Invoke) {
val args = invoke.parseArgs(SetEventHandlerArgs::class.java)
channel = args.handler
invoke.resolve()
}
}
仮に10msに1度 timestamp を送信するようにします
tauri-plugin-test/android/src/main/java/ExamplePlugin.kt
@TauriPlugin
class ExamplePlugin(
private val activity: Activity,
) : Plugin(activity) {
// ...
init {
Thread {
while (true) {
Thread.sleep(10)
channel?.let {
val payload = JSObject()
payload.put("timestamp", System.currentTimeMillis())
channel?.send(payload)
}
}
}.start()
}
//...
}
Rust側で初期化時に Channel を渡すようにします.
init 関数で↓のように setEventHandler を呼び出します.
ここでは受け取った timestamp を出力しています
tauri-plugin-[plugin-name]/src/mobile.rs
#[cfg(target_os = "android")]
use tauri::{
ipc::{Channel, InvokeResponseBody},
};
pub fn init<R: Runtime, C: DeserializeOwned>(
_app: &AppHandle<R>,
api: PluginApi<R, C>,
) -> crate::Result<R> {
#[cfg(target_os = "android")]
{
let handle = api.register_android_plugin("dev.satooru.tauritest01", "ExamplePlugin")?;
handle.run_mobile_plugin::<()>(
"setEventHandler",
SetEventHandlerArgs {
handler: Channel::new(move |event| {
if let InvokeResponseBody::Json(payload) = event {
if let Ok(data) = serde_json::from_str::<serde_json::Value>(&payload) {
let timestamp = data
.get("timestamp")
.and_then(|v| v.as_u64())
.unwrap_or_default();
println!("Received {}: ", timestamp);
}
}
Ok(())
})
},
)?;
Ok(Test(handle))
}
#[cfg(target_os = "ios")]
// 省略
}
fn setup_sensor_event_handler<R: Runtime>(
app_handle: &AppHandle<R>,
) -> Channel<InvokeResponseBody> {
let app_handle = app_handle.clone();
Channel::new(move |event| {
if let InvokeResponseBody::Json(payload) = event {
app_handle
.sensorkit()
.sensor_batch_service
.push(&app_handle, payload);
}
Ok(())
})
}
tauri-plugin-[plugin-name]/src/models.rs
#[cfg(target_os = "android")]
use tauri::ipc::Channel;
#[cfg(target_os = "android")]
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SetEventHandlerArgs {
pub(crate) handler: Channel,
}
動作確認
Logcat を確認すると大量のデータが受け取れているのを確認できます
また,適当なタイミングで止めてもタイムスタンプの順番がずれていないことも確認できます ワーイ
参考
