0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Tauri 2.0 Kotlinからチャンネル通信する方法

Last updated at Posted at 2026-01-31

本記事に誤りを見つけた場合は,コメントにて優しく教えていただけると助かります

はじめに

自作プラグインを作成すると 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 を確認すると大量のデータが受け取れているのを確認できます
また,適当なタイミングで止めてもタイムスタンプの順番がずれていないことも確認できます ワーイ

スクリーンショット 2026-02-01 5.05.42.png

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?