Android SDcard: Permission denied

693 views
Skip to first unread message

sergen

unread,
Nov 4, 2020, 2:27:54 PM11/4/20
to Kivy users support
Good day!

linux Mint 20, Python 3.8, Cython == 0.29.19, Buildozer 1.2.0, Kivy 1.10.1, Android 7
The Cython version is overstated, because other versions cannot be installed. "Pip" writes that I have Kivy 1.10.1 installed, but the Kivy itself claims that 1.11.1.

Compiling my application is smooth. The error occurs during startup. The program accesses the file on the SD card, an  error occurs : "PermissionError: [Errno 13] Permission denied" . At the same time, I indicated the necessary rights to read and write the SD card in the SPEC file. I read that android tightens the rights to access the application to data storage locations, but my android version 7 is quite old. I could not find a simple and clear answer on the Internet how to solve this problem.

There is an interesting fact, I additionally installed the KivyLauncher on the tablet. So the program runs from it without errors. Why does the access denial not apply to the launcher?
buildozer.spec

sergen

unread,
Nov 4, 2020, 2:28:54 PM11/4/20
to Kivy users support
среда, 4 ноября 2020 г. в 22:27:54 UTC+3, sergen:
error.txt

Robert Flatt

unread,
Nov 4, 2020, 6:35:46 PM11/4/20
to Kivy users support
have Kivy 1.10.1 installed, but the Kivy itself claims that 1.11.1.

Buildozer uses the version specified in requirements,  locally installed packages are ignored.

I could not find a simple and clear answer on the Internet how to solve this problem.
This I have experienced :(  The meanings change with Android version and it is not always clear if this is OS version or API version.

So, assuming the failing file path actually exists.....
It looks like the app tries to access a file on internal storage at some 'random' location.
Too much version specific noise for a clear comment, but generally Android only allowed that on external storage.
So that might be the issue.

Btw there is no need to use API 25 for Android 7 - not clear if you would be working around anything real by doing this.

When I don't understand a small test case usually helps, or at least means I can ask a simple question.
This should help you figure out what is going on, use buildozer defaults, except permission as noted:

import kivy
from kivy.app import App
from kivy.uix.label import Label
from android.storage import app_storage_path,primary_external_storage_path,\
    secondary_external_storage_path
from android.permissions import request_permissions, check_permission, \
   
Permission
from os.path import abspath
from os import getcwd

### Demonstrates the file paths for various Android storage locations
### on the current device (only)
### Demonstrates Android permission for access to Android shared storage
#########################################################################

###  Android  WRITE_EXTERNAL_STORAGE implies READ_EXTERNAL_STORAGE

###  In buildozer.spec:
###  android.permissions = WRITE_EXTERNAL_STORAGE
###
###  is not required for API 29 or greater  (I tested on a device with 29).
###  It MAY be required (I have not tested) for devices with API 28 or less.
###  At least, I think that is what this says:
###  https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE

class MyApp(App):

   
def permission_callback(self,permissions,grants):
       
if check_permission(Permission.WRITE_EXTERNAL_STORAGE):
           
self.label.text += 'Write Permission Granted\n'
       
else:
           
self.label.text += 'Write Permission Denied\n'
           
return
       
# Can only read/write after we have been granted permission
       
# The user may have denied permission
        filename
= join(primary_external_storage_path(),'Download/test.txt')
       
try:
           
with open(filename, 'w') as out_file:
                out_file
.write('Greetings Earthlings\n')
               
self.label.text += filename + ' created\n'
           
# Now look at this file with your File Manager app
       
except Exception as e:
           
self.label.text += str(e)

   
def build(self):
        text
= App.get_running_app().user_data_dir + '\n'
        text
+= self.user_data_dir + '\n'
        text
+= app_storage_path() + '\n'
        text
+= getcwd() + '\n'
        text
+= abspath('.') + '\n'   # . does work
        text
+= abspath('~') + '\n'   # ~ not the Bash interpretation
        text
+= abspath(__file__) +'\n'
       
self.label = Label(text=text)
       
# This is I think recomended for 26 thru 28 and later
       
# And maybe required 29 and greater depending on where accessed
       
# Permission requests are asynchronous, so you may need the callback.
        request_permissions
([Permission.WRITE_EXTERNAL_STORAGE],
                           
self.permission_callback)
       
# Note: Permission probably has not been granted yet.
       
# (You can see this because, on the device screen the 'Granted'
       
# message (above) occurs after the message below.)
       
# These are OK here because they don't read/write to storage.
       
self.label.text += primary_external_storage_path() +'\n'
       
if secondary_external_storage_path():
           
self.label.text += secondary_external_storage_path() +'\n'
       
else:
           
self.label.text += 'No secondary storage\n'
       
return self.label

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















sergen

unread,
Nov 5, 2020, 3:04:20 AM11/5/20
to Kivy users support
Test passed successfully. The application asked for permission to write files, I confirmed it. Now access to the SD card is open. I will implement this solution into my program.
Thank you very much! How many fought over this error, and the solution turned out to be so simple but not obvious.
четверг, 5 ноября 2020 г. в 02:35:46 UTC+3, planckp...@gmail.com:

sergen

unread,
Nov 5, 2020, 4:46:31 AM11/5/20
to Kivy users support
Made it even easier. I went to the "Settings" section on my tablet and gave my application permission to access the storages. I am ashamed to admit that I had not thought of this before.
Still, it's best to implement a forced permission request into a program.

четверг, 5 ноября 2020 г. в 11:04:20 UTC+3, sergen:

Robert Flatt

unread,
Nov 5, 2020, 12:05:41 PM11/5/20
to Kivy users support
yes, Settings changes the same internal state. Well found.
Reply all
Reply to author
Forward
0 new messages