mirror of
https://github.com/godotengine/godot.git
synced 2025-12-08 06:09:55 +00:00
Merge pull request #113367 from syntaxerror247/persistable_uri_perm
Android: Add method to take persistable URI permission
This commit is contained in:
commit
bed803fcda
3 changed files with 37 additions and 18 deletions
|
|
@ -790,8 +790,17 @@
|
||||||
[b]Note:[/b] On macOS, sandboxed apps will save security-scoped bookmarks to retain access to the opened folders across multiple sessions. Use [method OS.get_granted_permissions] to get a list of saved bookmarks.
|
[b]Note:[/b] On macOS, sandboxed apps will save security-scoped bookmarks to retain access to the opened folders across multiple sessions. Use [method OS.get_granted_permissions] to get a list of saved bookmarks.
|
||||||
[b]Note:[/b] On Android, this method uses the Android Storage Access Framework (SAF).
|
[b]Note:[/b] On Android, this method uses the Android Storage Access Framework (SAF).
|
||||||
The file picker returns a URI instead of a filesystem path. This URI can be passed directly to [FileAccess] to perform read/write operations.
|
The file picker returns a URI instead of a filesystem path. This URI can be passed directly to [FileAccess] to perform read/write operations.
|
||||||
When using [constant FILE_DIALOG_MODE_OPEN_DIR], it returns a tree URI that grants full access to the selected directory. File operations inside this directory can be performed by passing a path in the form [code]treeUri#relative/path/to/file[/code] to [FileAccess].
|
When using [constant FILE_DIALOG_MODE_OPEN_DIR], it returns a tree URI that grants full access to the selected directory. File operations inside this directory can be performed by passing a path on the form [code]treeUri#relative/path/to/file[/code] to [FileAccess].
|
||||||
Tree URIs should be saved and reused; they remain valid across app restarts as long as the directory is not moved, renamed, or deleted.
|
To avoid opening the file picker again after each app restart, you can take persistable URI permission as follows:
|
||||||
|
[codeblocks]
|
||||||
|
[gdscript]
|
||||||
|
val uri = "content://com.android..." # URI of the selected file or folder.
|
||||||
|
val persist = true # Set to false to release the persistable permission.
|
||||||
|
var android_runtime = Engine.get_singleton("AndroidRuntime")
|
||||||
|
android_runtime.updatePersistableUriPermission(uri, persist)
|
||||||
|
[/gdscript]
|
||||||
|
[/codeblocks]
|
||||||
|
The persistable URI permission remains valid across app restarts as long as the directory is not moved, renamed, or deleted.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="file_dialog_with_options_show">
|
<method name="file_dialog_with_options_show">
|
||||||
|
|
|
||||||
|
|
@ -85,28 +85,12 @@ internal class FilePicker {
|
||||||
for (i in 0 until clipData.itemCount) {
|
for (i in 0 until clipData.itemCount) {
|
||||||
val uri = clipData.getItemAt(i).uri
|
val uri = clipData.getItemAt(i).uri
|
||||||
uri?.let {
|
uri?.let {
|
||||||
try {
|
|
||||||
context.contentResolver.takePersistableUriPermission(
|
|
||||||
it,
|
|
||||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
|
||||||
)
|
|
||||||
} catch (e: SecurityException) {
|
|
||||||
Log.d(TAG, "Unable to persist URI: $it", e)
|
|
||||||
}
|
|
||||||
selectedFiles.add(it.toString())
|
selectedFiles.add(it.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val uri: Uri? = data?.data
|
val uri: Uri? = data?.data
|
||||||
uri?.let {
|
uri?.let {
|
||||||
try {
|
|
||||||
context.contentResolver.takePersistableUriPermission(
|
|
||||||
it,
|
|
||||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
|
||||||
)
|
|
||||||
} catch (e: SecurityException) {
|
|
||||||
Log.w(TAG, "Unable to persist URI: $it", e)
|
|
||||||
}
|
|
||||||
selectedFiles.add(it.toString())
|
selectedFiles.add(it.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,10 @@
|
||||||
|
|
||||||
package org.godotengine.godot.plugin
|
package org.godotengine.godot.plugin
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
|
||||||
import org.godotengine.godot.Godot
|
import org.godotengine.godot.Godot
|
||||||
import org.godotengine.godot.variant.Callable
|
import org.godotengine.godot.variant.Callable
|
||||||
|
|
||||||
|
|
@ -39,6 +43,8 @@ import org.godotengine.godot.variant.Callable
|
||||||
* @see <a href="https://docs.godotengine.org/en/latest/tutorials/platform/android/javaclasswrapper_and_androidruntimeplugin.html">Integrating with Android APIs</a>
|
* @see <a href="https://docs.godotengine.org/en/latest/tutorials/platform/android/javaclasswrapper_and_androidruntimeplugin.html">Integrating with Android APIs</a>
|
||||||
*/
|
*/
|
||||||
class AndroidRuntimePlugin(godot: Godot) : GodotPlugin(godot) {
|
class AndroidRuntimePlugin(godot: Godot) : GodotPlugin(godot) {
|
||||||
|
private val TAG = AndroidRuntimePlugin::class.java.simpleName
|
||||||
|
|
||||||
override fun getPluginName() = "AndroidRuntime"
|
override fun getPluginName() = "AndroidRuntime"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -68,4 +74,24 @@ class AndroidRuntimePlugin(godot: Godot) : GodotPlugin(godot) {
|
||||||
fun createCallableFromGodotCallable(godotCallable: Callable): java.util.concurrent.Callable<Any> {
|
fun createCallableFromGodotCallable(godotCallable: Callable): java.util.concurrent.Callable<Any> {
|
||||||
return java.util.concurrent.Callable { godotCallable.call() }
|
return java.util.concurrent.Callable { godotCallable.call() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to take/release persistable URI permission.
|
||||||
|
*/
|
||||||
|
@UsedByGodot
|
||||||
|
fun updatePersistableUriPermission(uriString: String, persist: Boolean): Boolean {
|
||||||
|
try {
|
||||||
|
val uri = uriString.toUri()
|
||||||
|
val contentResolver = context.contentResolver
|
||||||
|
if (persist) {
|
||||||
|
contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
|
} else {
|
||||||
|
contentResolver.releasePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
|
}
|
||||||
|
} catch (e: RuntimeException) {
|
||||||
|
Log.d(TAG, "Error updating persistable permission: ", e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue