godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.12k stars 20.2k forks source link

Save file in Android system storage #23004

Closed deepmax closed 3 years ago

deepmax commented 5 years ago

Godot version: v3.0.6.stable

OS/device including version: Ubuntu 14.04

Issue description: Can't save file in Android system or external storage and gives error ERR_FILE_CANT_OPEN.

    var file = File.new()

        var name = OS.get_system_dir(OS.SYSTEM_DIR_DOCUMENTS) + "/mydata.dat"

        var err = file.open(name, File.WRITE)

        print(FILE_NAME)

        print(err)

Output:

/storage/emulated/0/Documents 12

These permissions are set (which I'm not sure if they're enough):

READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
KoBeWi commented 4 years ago

Can anyone still reproduce this bug in Godot 3.2.1 or any later release (e.g. 3.2.2-rc4)?

If yes, please ensure that an up-to-date Minimal Reproduction Project (MRP) is included in this report (a MRP is a zipped Godot project with the minimal elements necessary to reliably trigger the bug). You can upload ZIP files in an issue comment with a drag and drop.

Constannnnnt commented 4 years ago

I guess there is a similar issue #39414

Calinou commented 4 years ago

@Constannnnnt These issues have a difference: #39414 is about saving in the app-specific folder, whereas this one is about saving in the user's Documents folder.

volzhs commented 4 years ago

I don't know whole android code for godot, but I got a possible cause. https://github.com/godotengine/godot/blob/b55d859c5f092d145cd0d2c8df9ac5d42c500626/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java#L557

getExternalStoragePublicDirectory is deprecated in API 29. https://developer.android.com/reference/android/os/Environment.html#getExternalStoragePublicDirectory(java.lang.String)

This method was deprecated in API level 29. To improve user privacy, direct access to shared/external storage devices is deprecated. When an app targets Build.VERSION_CODES.Q, the path returned from this method is no longer directly accessible to apps. Apps can continue to access content stored on shared/external storage by migrating to alternatives such as Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENT.

reptofrog commented 4 years ago

Are any temporary workarounds possible?

I really need the ability to somehow save images for my Android project, but save_png fails.

EXOMODE commented 3 years ago

Before writing to the device (both external and internal card), call the access request logic processing, for example:

var has_permissions: bool = false

while not has_permissions:
    var permissions: PackedStringArray = OS.get_granted_permissions()
    #var permissions: Array = OS.get_granted_permissions() - for Godot 3 branch

    if not permissions.has("android.permission.READ_EXTERNAL_STORAGE") \
        or not permissions.has("android.permission.WRITE_EXTERNAL_STORAGE"):
        OS.request_permissions()
        await get_tree().create_timer(1).timeout
        #yield(get_tree().create_timer(1), "timeout") - for Godot 3 branch
    else:
        has_permissions = true
dirkk0 commented 3 years ago

Thanks to @Exomode hint, I was able to implement a minimal mp3 player that is able to access the music files on Android: https://github.com/dirkk0/minimal-mp3player

EXOMODE commented 3 years ago

Благодаря подсказке @Exomode мне удалось реализовать минимальный mp3-плеер, который может получить доступ к музыкальным файлам на Android: https://github.com/dirkk0/minimal-mp3player

I was happy to help :) Remember that my method only works up to API 28 (inclusive). For API 29 there is an additional solution, for API 30 and future there are still access problems and their solution will require patching the engine.

dirkk0 commented 3 years ago

Before we talked, I successfully deployed my project to an Android 6 phone (old Nexus 5) and to a Pixel4 with Android 11, where it wouldn't work. Then I forgot about it and accidentally started the App on the Pixel4 today and ... ... lo and behold, it was working! I could see (and play) the files in the music folder. Obviously there was a system update that fixed(?)/changed(?) something!?

m4gr3d commented 3 years ago

Duplicate of https://github.com/godotengine/godot/issues/38913