Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't write ti SD-card on Android 6.0.1 #1024

Closed
BorisTestov opened this issue Mar 21, 2017 · 16 comments
Closed

Can't write ti SD-card on Android 6.0.1 #1024

BorisTestov opened this issue Mar 21, 2017 · 16 comments

Comments

@BorisTestov
Copy link

Hello everyone! So, I'm trying to create an empty file on SD-card. I've two phones, first with Android 4.4 and second with Android 6.0.1. My application works very well on the first phone, but not on the second. I heard, that there is a new permission for writing on SD-card on Android 6.0.1: WRITE_MEDIA_STORAGE. But with this permission I have the following error:
"android.permission" contain an unknown permission WRITE_MEDIA_STORAGE
So, the question is: how to write on SD-card on Android 6.0.1?

@KeyWeeUsr
Copy link
Contributor

I believe the permission is the same - WRITE_EXTERNAL_STORAGE, but the way how to use it is a little bit different. I don't have 6.0+ though, so I can't really say how does it work with Kivy/P4A. If it doesn't out of box, you might need to use Pyjnius to write the same code as in the linked question.

@llfkj
Copy link

llfkj commented Mar 23, 2017

I'm currently writing to /sdcard on Android 6.0.1 without any special effort. (that's where the kivy writes its ini files, for instance). Can you show the actual code and error messages?

@guysoft
Copy link

guysoft commented Jan 12, 2019

Hey, was this fixed? Is there a way at all to write to sdcard using kivy and modern android?

@ghost
Copy link

ghost commented Jan 12, 2019

@guysoft not yet, fix is here but not merged: #1528

@guysoft
Copy link

guysoft commented Jan 12, 2019

I think it can be done using jnius.

Here it says you need to open the OPEN_DOCUMENT_TREE intent and pick the external sdcard. Then run :

        Uri treeUri = resultData.getData();
        DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
        grantUriPermission(getPackageName(), treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        copyFile(sdCard.toString(), "/File.txt", path + "/new", pickedDir);

I managed to open the tree file and get the uri, but I can't find how to call grantUriPermission. But I can't find how to call that.

Here is what I have:

import kivy

from kivy.app import App
from kivy.uix.button import Button
from jnius import cast
from jnius import autoclass
import os
from android import activity

# Forum discussion: https://groups.google.com/forum/#!msg/kivy-users/bjsG2j9bptI/-Oe_aGo0newJ
def on_activity_result(request_code, result_code, intent):  
    PythonActivity = autoclass('org.kivy.android.PythonActivity')
    currentActivity = cast('android.app.Activity', PythonActivity.mActivity)
    uri = str(selectedImage.toString())
    print(uri)

    return
    
    
class MyApp(App):

    def callback(self, data):
        print("Started folder picker")

        # import the needed Java class
        
        PythonActivity = autoclass('org.kivy.android.PythonActivity')
        Intent = autoclass('android.content.Intent')
        Uri = autoclass('android.net.Uri')

        # create the intent
        intent = Intent()
        intent.setAction(Intent.ACTION_OPEN_DOCUMENT_TREE)
        currentActivity = cast('android.app.Activity', PythonActivity.mActivity)
        activity.bind(on_activity_result=on_activity_result)
        currentActivity.startActivityForResult(intent, 1)

    def build(self):
        return Button(text='Hello world', on_press=self.callback)


if __name__ == '__main__':
    MyApp().run()

@ghost
Copy link

ghost commented Jan 12, 2019

@gdyuldin if you use #1528 's branch and use the permission api, you can do it like this (although you'll need to check if the permission was granted with a timer, there is no callback support yet):

from android.permissions import Permission, request_permission, check_permission

if not check_permissions(Permission.WRITE_EXTERNAL_STORAGE):
    request_permission(Permission.WRITE_EXTERNAL_STORAGE)

After you gained permission, you can just use regular open()/python file io to read and write files from the sdcard

@guysoft
Copy link

guysoft commented Jan 12, 2019

@Jonast
Sorry if off topic:
How do I make my buildozer build from a different kivy repo?
I want to merge this branch with up to date master on my own fork

@ghost
Copy link

ghost commented Jan 12, 2019

@guysoft sorry I really don't know, I don't use buildozer myself (I use p4a directly)

@hackalog
Copy link

hackalog commented Jan 12, 2019

@Jonast You could just modify the URL in the kivy recipe to point to your repo/branch.

I have a WIP where I also pass owner and name (in addition to version, which is already there) to the recipe code so you can use something like this in a recipe. If it's of interest, I could clean it up and submit a PR

name=kivy
version=master
owner=hackalog
url = https://github.com/{owner}/{name}/archive/{version}.zip

@ghost
Copy link

ghost commented Jan 12, 2019

@hackalog wouldn't it make more sense to just add repo-url or something and allow a {version} placeholder in there? Because otherwise you'll have it more flexible but just not flexible enough to fetch it from GitLab, bitbucket or somewhere else, which seems like a strange limitation

@hackalog
Copy link

Yes, the url is just a format string. Values are just passed as a dict, so they can be optionally present when formatting the URL string. That's how {version} works now. I've just added additional variables to that dict so they can be used when crafting a url format wting.

You can change the url-string to anything you want. if you know the owner, repo name (or name) and version, you should be able to build a valid URL for bitbucket, gitlab, or whatever.

@ghost
Copy link

ghost commented Jan 12, 2019

Are the repo + owner names used anywhere else? If not it seems a bit redundant to have them separately. But apart from that, this sounds like a very useful addition worth a buildozer pull request

@guysoft
Copy link

guysoft commented Jan 12, 2019

Ok, got it building from that fork which I merged with master. Its done by pointing in buildozser.spec
p4a.source_dir = /path/to/p4a.

Using #1528 fails for me because of outdated -mandroid flag:
I didn't have jnius as a dependency, but it still requires it.

STDOUT:building 'jnius' extension
arm-linux-androideabi-gcc -DANDROID -fomit-frame-pointer -D__ANDROID_API__=21 -mandroid -isystem /home/buildozer/.buildozer/android/platform/android-ndk-r18b/sysroot/usr/include/arm-linux-androideabi -I/home/buildozer/.buildozer/android/platform/android-ndk-r18b/sysroot/usr/include/arm-linux-androideabi -isysroot /home/buildozer/.buildozer/android/platform/android-ndk-r18b/sysroot -I/buildozer/.buildozer/android/platform/build/build/python-installs/myapp/include/python2.7 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DANDROID -fomit-frame-pointer -D__ANDROID_API__=21 -mandroid -isystem /home/buildozer/.buildozer/android/platform/android-ndk-r18b/sysroot/usr/include/arm-linux-androideabi -I/home/buildozer/.buildozer/android/platform/android-ndk-r18b/sysroot/usr/include/arm-linux-androideabi -isysroot /home/buildozer/.buildozer/android/platform/android-ndk-r18b/sysroot -I/buildozer/.buildozer/android/platform/build/build/python-installs/myapp/include/python2.7 -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -mthumb -I/buildozer/.buildozer/android/platform/build/build/other_builds/python2/armeabi-v7a__ndk_target_21/python2/Include -fPIC -I/buildozer/.buildozer/android/platform/build/build/other_builds/hostpython2/desktop/hostpython2/Include -I/buildozer/.buildozer/android/platform/build/build/other_builds/hostpython2/desktop/hostpython2/native-build -c jnius/jnius.c -o build/temp.linux-x86_64-2.7/jnius/jnius.o
clang: error: unknown argument: '-mandroid'
clang: error: unknown argument: '-mandroid'
error: command 'arm-linux-androideabi-gcc' failed with exit status 1


  STDERR:


                                                                                                  [INFO]:    STDOUT:
        running build_ext
building 'jnius' extension                                                                                     
arm-linux-androideabi-gcc -DANDROID -fomit-frame-pointer -D__ANDROID_API__=21 -mandroid -isystem /home/buildozer/.buildozer/android/platform/android-ndk-r18b/sysroot/usr/include/arm-linux-androideabi -I/home/buildozer/.buildozer/android/platform/android-ndk-r18b/sysroot/usr/include/arm-linux-androideabi -isysroot /home/buildozer/.buildozer/android/platform/android-ndk-r18b/sysroot -I/buildozer/.buildozer/android/platform/build/build/python-installs/myapp/include/python2.7 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DANDROID -fomit-frame-pointer -D__ANDROID_API__=21 -mandroid -isystem /home/buildozer/.buildozer/android/platform/android-ndk-r18b/sysroot/usr/include/arm-linux-androideabi -I/home/buildozer/.buildozer/android/platform/android-ndk-r18b/sysroot/usr/include/arm-linux-androideabi -isysroot /home/buildozer/.buildozer/android/platform/android-ndk-r18b/sysroot -I/buildozer/.buildozer/android/platform/build/build/python-installs/myapp/include/python2.7 -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -mthumb -I/buildozer/.buildozer/android/platform/build/build/other_builds/python2/armeabi-v7a__ndk_target_21/python2/Include -fPIC -I/buildozer/.buildozer/android/platform/build/build/other_builds/hostpython2/desktop/hostpython2/Include -I/buildozer/.buildozer/android/platform/build/build/other_builds/hostpython2/desktop/hostpython2/native-build -c jnius/jnius.c -o build/temp.linux-x86_64-2.7/jnius/jnius.o            
clang: error: unknown argument: '-mandroid'                                                                    
clang: error: unknown argument: '-mandroid'                                                                    
error: command 'arm-linux-androideabi-gcc' failed with exit status 1                                           
[INFO]:    STDERR:

[INFO]:    COMMAND:
cd /buildozer/.buildozer/android/platform/build/build/other_builds/pyjnius-python2-sdl2/armeabi-v7a__ndk_target_21/pyjnius && /buildozer/.buildozer/android/platform/build/build/other_builds/hostpython2/desktop/hostpython2/native-build/python setup.py build_ext -v
                           

@ghost
Copy link

ghost commented Jan 12, 2019

@guysoft the android module in #1528 actually uses pyjnius internally to communicate with the PythonActivity, so it becomes a dependency of that (which it isn't on master)

@ghost ghost self-assigned this Jan 15, 2019
@guysoft
Copy link

guysoft commented Jan 16, 2019

@Jonast ok after merging and using #1528 , it still does not work. I made a small repo with simple reproduction steps so you can try it out and we can look at the same code, have a feeling you might spot the error if you take a look, instructions in a comment in the PR, It also uses your docker images that are now hosted on github 🙂 :
#1528 (comment)

@ghost ghost added the work in progress label Jan 26, 2019
@ghost
Copy link

ghost commented Jan 26, 2019

The permission API is now implemented with on master with #1528 merged, even though the callback mechanism probably would still be worth adding at some point.

The functionality is documented here:

https://github.com/kivy/python-for-android/blob/master/doc/source/apis.rst#runtime-permissions

The latest kivy development version should also per default save the config to a writable location now (without any more general sd card permissions necessary)

@ghost ghost closed this as completed Jan 26, 2019
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants