tauri-apps / plugins-workspace

All of the official Tauri plugins in one place!
https://tauri.app
Apache License 2.0
944 stars 264 forks source link

[v2-rc] [android] ActivityCallback from startActivityForResult in Kotlin/Java may not call. #1741

Open aiueo13 opened 2 months ago

aiueo13 commented 2 months ago

The sentences may be vague because of my not good English :(

Description

This is an issue when creating and using mobile plugins. When retrieving selected data from other applications in Android Kotlin / java, startActivityForResult is used, but this result, function with @ActivityCallback, is sometimes not returned or reflected with a delay.

Reproduction

This can be verified with Function of FileDialogBuilder::pick_file of tauri-plugin-dialog.

The results may not be returned when using this on Android to call the file picker, select or cancel a file and return to its own application. Sometimes they succeed, sometimes they fail continuously as it.

If it fails, no matter how long you wait, it will not get the result, but if you call the same command again and it succeeds, the results that have not returned so far will also be reflected with delayed. When it, the calling order is maintained and the results are returned. Act as if thread had stopped then restarted.

Info

Confirmed at least on Android 13 (Both Dev and Release Build).

aiueo13 commented 1 month ago

In addition, the onNewIntent method called when called as an Intent from another app may also not be called or may be called late. It may be that the problem occurs when returning to own Activity from another Activity.

I will create details and a reproduction repository in the near future :>

aiueo13 commented 1 month ago

I found a temporary solution. So I am writing this for people who are having the same problem. Invoking rust command in frontend javascript reflects the result of ActivityCallback with a certain probability.

In other words, before calling a function such as dialog.open, you set it to call some rust command at regular intervals in frontend’s javascript side, and then turn it off after the target function is reflected. In that case, it must be called via setInterval rather than a recurrent call to setTimeout.

rust

#[tauri::command]
pub fn noop() {
   // Do nothing
}

javascript

async function openDialog() {
  const iid = setInterval(async () => await invoke("noop", {}), 200)
  try {
    return await dialog.open() 
  }
  finally {
    clearInterval(iid)
  }
}