tauri
tauri copied to clipboard
[bug] Kotlin can't Trigger events to Rust or JS
Describe the bug
When I add a listener for Trigger in Kotlin... ( https://v2.tauri.app/develop/plugins/develop-mobile/#plugin-events )
I get a permission error ( with seemingly no possible way to give this permission in default.json ) "Error setting up listeners: Command plugin:theplug|registerListener not allowed by ACL"
Also - it seems not possible for Kotlin to trigger a function in Rust ? ( commands.rs or otherwise )
Reproduction
1 - create an Android plugin 2 - add some commands in comands.rs / mobile.rs / desktop.rs 3 - add a Kotlin Trigger that sends a message to JS
We get this error Error setting up listeners: Command plugin:theplug|registerListener not allowed by ACL
Expected behavior
The provided example should work https://v2.tauri.app/develop/plugins/develop-mobile/#plugin-events
Also - it would be great if we could app.emit from Kotlin - then listen in Rust / JS - it seems not possible ?
Full tauri info output
Error setting up listeners: Command plugin:theplug|registerListener not allowed by ACL
Stack trace
Additional context
No response
I've been going through the same problem. mine is a bit different though I'm not getting any errors it's just silent failure.
Kotlin code:
package com.plugin.rt.test
import android.app.Activity
import android.webkit.WebView
import app.tauri.annotation.Command
import app.tauri.annotation.InvokeArg
import app.tauri.annotation.TauriPlugin
import app.tauri.plugin.Invoke
import app.tauri.plugin.JSObject
import app.tauri.plugin.Plugin
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@InvokeArg
class PingArgs {
var value: String? = null
}
@TauriPlugin
class ExamplePlugin(private val activity: Activity) : Plugin(activity) {
private val implementation = Example()
@Command
fun ping(invoke: Invoke) {
val args = invoke.parseArgs(PingArgs::class.java)
val ret = JSObject()
ret.put("value", implementation.pong(args.value ?: "default value :("))
invoke.resolve(ret)
}
override fun load(webView: WebView) {
startPeriodicTrigger()
}
private var timerJob: Job? = null
fun startPeriodicTrigger() {
timerJob =
CoroutineScope(Dispatchers.IO).launch {
while (true) {
val ret =
JSObject().apply {
put("message", "Test message")
put("timestamp", System.currentTimeMillis())
}
println("Hello corutine msg called")
trigger("custom-event-name", ret)
delay(3000) // Wait 3 seconds
}
}
}
}
Rust listener:
use tauri::Listener;
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_rt_test::init())
.setup(|app| {
let handle = app.handle().clone();
handle.clone().listen_any("custom-event-name", move |e| {
println!("Got mock msg: {:?}", e);
// handle.exit(0);
});
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
html:
<html>
<head>
<script defer>
function my_log(input) {
const newDiv = document.createElement("div");
newDiv.textContent = JSON.stringify(input, null, 2);
document.body.appendChild(newDiv);
}
async function main() {
try {
await window.__TAURI__.event.listen(
"custom-event-name",
(e) => {
my_log(e);
},
);
my_log("Valid listener mounted");
} catch (e) {
my_log(e);
}
}
main();
</script>
</head>
<body>
<div>Plugin example</div>
</body>
</html>
If I emit event from Rust it's just expected behavior. Emitting from Kotlin is just as if it's doing nothing.
Does anyone know any other way to extract data from native Kotlin code into Rust/JS?
I create a full example on this issue: https://github.com/F8RZD/tauri-kotlin-problem
This is undocumented, but you have to add two built-in commands registerListener and unregister_listener in your commands list and add them to the default permissions.
diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-tts/build.rs b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-tts/build.rs
index e6bab73..e41f12a 100644
--- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-tts/build.rs
+++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-tts/build.rs
@@ -13,6 +13,8 @@ const COMMANDS: &[&str] = &[
"get_all_voices",
"get_granularities",
"get_speaking_lang",
+ "registerListener",
+ "unregister_listener",
];
fn main() {
--- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-tts/permissions/default.toml
+++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-tts/permissions/default.toml
@@ -15,4 +15,6 @@ permissions = [
"allow-get-all-voices",
"allow-get-granularities",
"allow-get-speaking-lang",
+ "allow-registerListener",
+ "allow-unregister-listener",
]
@FabianLars Are there any plans to standardize the naming convention between registerListener and unregister_listener to make them consistent?
UPDATE: I see #12486 is on this. I will watch on it.
@chrox Thank you so much for this comment!
I was following the code of the official notification plugin and it uses register_listener. How come the hyphenated/snakecase version works there? Or does it (I'm not using that plugin, yet)?
@chrox Thank you so much for this comment!
I was following the code of the official notification plugin and it uses
register_listener. How come the hyphenated/snakecase version works there? Or does it (I'm not using that plugin, yet)?
I'm not using the notification plugin but from the tauri core API registerListener is used instead of register_listener.
async function addPluginListener<T>(
plugin: string,
event: string,
cb: (payload: T) => void
): Promise<PluginListener> {
const handler = new Channel<T>(cb)
return invoke(`plugin:${plugin}|registerListener`, { event, handler }).then(
() => new PluginListener(plugin, event, handler.id)
)
}
This is undocumented, but you have to add two built-in commands
registerListenerandunregister_listenerin your commands list and add them to the default permissions.diff --git a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-tts/build.rs b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-tts/build.rs index e6bab73..e41f12a 100644 --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-tts/build.rs +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-tts/build.rs @@ -13,6 +13,8 @@ const COMMANDS: &[&str] = &[ "get_all_voices", "get_granularities", "get_speaking_lang",
- "registerListener",
- "unregister_listener", ];
fn main() { --- a/apps/readest-app/src-tauri/plugins/tauri-plugin-native-tts/permissions/default.toml +++ b/apps/readest-app/src-tauri/plugins/tauri-plugin-native-tts/permissions/default.toml @@ -15,4 +15,6 @@ permissions = [ "allow-get-all-voices", "allow-get-granularities", "allow-get-speaking-lang",
- "allow-registerListener",
- "allow-unregister-listener", ]
For those who use Tauri 2.9.0+, you might need add allow-register-listener permission instead of allow-registerListener, and add registerListener command instead of registerListener after https://github.com/tauri-apps/tauri/pull/14132. Unfortunately this is not documented neither at https://tauri.app/develop/plugins/develop-mobile/#plugin-events nor at https://tauri.app/reference/javascript/api/namespacecore/#addpluginlistener.