I tried multiple ways to create a directory in documents using kivy (JiCsingApp, to preserve previous data), but somehow it seems that none of them is right, I always receive the error: [Errno 13] Permission denied. I would appreciate if someone could help me out with this problem. I also receive an error message if I create a simple file. If I manually give the permission, the program runs without an error.
Here comes Python:
#....
from kivy.utils import platform
from kivy.logger import Logger
from jnius import autoclass
from plyer import storagepath
...
if platform == 'android':
from android.permissions import request_permissions, Permission, check_permission
from android.storage import app_storage_path, primary_external_storage_path, secondary_external_storage_path
...
def build(self):
self.title = '易經'
self.theme_cls.theme_style = "Light"
self.theme_cls.primary_palette = "Black"
if platform == 'android':
self.request_android_permissions()
else:
self.store = self.get_store()
return Builder.load_file('oracle.kv')
def request_android_permissions(self):
permissions = [Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE]
request_permissions(permissions, self.on_permissions_granted)
def on_permissions_granted(self, permissions, grants):
if all(grants):
self.store = self.get_store()
else:
Logger.error("Permissions were not granted.")
self.exit_app()
def create_app_directory(self):
Environment = autoclass('android.os.Environment')
File = autoclass('java.io.File')
app_folder = File(Environment.getExternalStorageDirectory(), 'JiCsingApp')
if not app_folder.exists():
if app_folder.mkdirs():
print(f"Directory {app_folder.getAbsolutePath()} created")
return app_folder.getAbsolutePath()
else:
raise PermissionError(f"Failed to create directory:{app_folder.getAbsolutePath()}")
else:
print(f"Directory {app_folder.getAbsolutePath()} already exists")
return app_folder.getAbsolutePath()
def get_store(self):
json_file_path = None
if platform == 'android':
app_directory = app_storage_path()
try:
# Call the method to create app directory
app_directory = self.create_app_directory()
print(f"App directory created at: {app_directory}")
except Exception as e:
print(f"Encountered error during directory creation: {e}")
try:
# Call the method to create app directory
app_directory = os.path.join(storagepath.get_home_dir(), 'JiCsingApp')
if not os.path.exists(app_directory):
os.mkdir(app_directory)
except Exception as e:
print(f"Encountered error during directory creation: {e}")
json_file_path = os.path.join(app_directory, 'prophecies.json')
else:
# For other platforms (Windows, MacOS, Linux)
json_file_path = 'prophecies.json'
Logger.info(f"Using JSON store at: {json_file_path}")
return JsonStore(json_file_path)
def on_start(self):
# Call the initialize_images method when the app starts
if not self.check_storage_permission():
self.request_android_permissions()
self.initialize_images()
def check_storage_permission(self):
# Check if the necessary permissions are already granted
return (check_permission(Permission.WRITE_EXTERNAL_STORAGE) and
check_permission(Permission.READ_EXTERNAL_STORAGE))
And here is my buildozer.spec file (relevant parts as far as I know):
requirements = plyer, jnius, kivy, https://github.com/kivymd/kivymd/archive/master.zip ...
...
# (list) Permissions
# (See https://python-for-android.readthedocs.io/en/latest/buildoptions/#build-options-1 for all the supported syntaxes and properties)
# android.permissions = android.permission.INTERNET, (name=android.permission.WRITE_EXTERNAL_STORAGE;maxSdkVersion=18)
android.permissions = android.permission.INTERNET, android.permission.WRITE_EXTERNAL_STORAGE,android.permission.READ_EXTERNAL_STORAGE, android.permission.MANAGE_EXTERNAL_STORAGE
Thanks for anyone, who can help in advance!
If you want access to all files, I've been using this on my Android device and a couple others and it works perfectly.
Download
folder but you have to request permission for othersbuildozer.spec
file add permission specification: android.permissions = MANAGE_EXTERNAL_STORAGE
And add pyjnius
to access JAVA Classes:
requirements = python3,kivy,pyjnius
# main.py
def requestAccessToAllFiles():
from jnius import autoclass
PythonActivity = autoclass('org.kivy.android.PythonActivity')
Environment = autoclass('android.os.Environment')
Uri = autoclass('android.net.Uri')
Intent = autoclass('android.content.Intent')
Settings = autoclass('android.provider.Settings')
mActivity = PythonActivity.mActivity
if not Environment.isExternalStorageManager(): # Checks if already Managing stroage
intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
intent.setData(Uri.parse(f"package:{mActivity.getPackageName()}")) # package:package.domain.package.name
mActivity.startActivity(intent)
# Then to create folder
from android.storage import primary_external_storage_path
import os
your_folder_path=os.join.path(primary_external_storage_path
(),"JiCsingApp")
os.mkdir(your_folder_path)
Hope this helped, if you need anything Android related try adding JAVA at the back of your search, I pieced together the function to request access to all files from JAVA stack answers