Kivy安卓端全文件访问权限请求及目录创建权限被拒问题求助
安卓Kivy应用创建目录权限被拒问题解决方案
问题概述
在安卓平台的Kivy应用中尝试创建JiCsingApp目录保存历史数据时,反复触发[Errno 13] Permission denied错误,手动授予权限后程序可正常运行。以下是针对该问题的分析与修复方案,包含修改后的代码及配置。
核心问题与修复要点
Android 10+存储机制限制
Android 10(API 29)及以上版本启用分区存储,直接在外部存储根目录创建文件夹需MANAGE_EXTERNAL_STORAGE权限,且该权限无法通过代码自动获取,必须引导用户前往系统设置手动开启。权限请求逻辑漏洞
原代码在build和on_start中重复发起权限请求,且未处理MANAGE_EXTERNAL_STORAGE的特殊申请流程,导致权限未完全生效时就执行目录创建操作。优先使用应用专属存储
推荐使用应用专属存储路径(无需额外权限),既符合安卓存储规范,又能避免权限问题;若必须使用公共存储,需补充引导用户开启全存储访问权限的逻辑。
修改后的Python代码
#.... from kivy.utils import platform from kivy.logger import Logger from jnius import autoclass from plyer import storagepath import os from kivy.storage.jsonstore import JsonStore ... 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" 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 request_manage_storage_permission(self): # 引导用户前往系统设置开启全存储访问权限 Intent = autoclass('android.content.Intent') Uri = autoclass('android.net.Uri') Settings = autoclass('android.provider.Settings') package_name = autoclass('android.app.ActivityThread').currentApplication().getPackageName() intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) intent.setData(Uri.parse(f"package:{package_name}")) autoclass('org.kivy.android.PythonActivity').mActivity.startActivity(intent) def on_permissions_granted(self, permissions, grants): if all(grants): # 针对Android 10+检查全存储访问权限 if platform == 'android': SDK_INT = autoclass('android.os.Build$VERSION').SDK_INT if SDK_INT >= 30: Environment = autoclass('android.os.Environment') if not Environment.isExternalStorageManager(): self.request_manage_storage_permission() return self.store = self.get_store() else: Logger.error("基础存储权限未授予,程序将退出") self.exit_app() def create_app_directory(self): # 优先使用应用专属外部存储路径,无需特殊权限 if platform == 'android': package_name = autoclass('android.app.ActivityThread').currentApplication().getPackageName() app_folder_path = os.path.join( primary_external_storage_path(), 'Android', 'data', package_name, 'files', 'JiCsingApp' ) else: app_folder_path = 'JiCsingApp' if not os.path.exists(app_folder_path): os.makedirs(app_folder_path) print(f"目录 {app_folder_path} 创建成功") else: print(f"目录 {app_folder_path} 已存在") return app_folder_path def get_store(self): json_file_path = None if platform == 'android': try: app_directory = self.create_app_directory() print(f"应用目录路径: {app_directory}") except Exception as e: print(f"创建目录时出错: {e}") # fallback到应用内部存储 app_directory = app_storage_path() json_file_path = os.path.join(app_directory, 'prophecies.json') else: # 其他平台(Windows, MacOS, Linux) json_file_path = 'prophecies.json' Logger.info(f"使用JSON存储路径: {json_file_path}") return JsonStore(json_file_path) def on_start(self): # 启动时统一处理权限与存储初始化 if platform == 'android': if self.check_storage_permission(): SDK_INT = autoclass('android.os.Build$VERSION').SDK_INT if SDK_INT >= 30: Environment = autoclass('android.os.Environment') if not Environment.isExternalStorageManager(): self.request_manage_storage_permission() return self.store = self.get_store() else: self.request_android_permissions() else: self.store = self.get_store() self.initialize_images() def check_storage_permission(self): # 检查基础读写存储权限 return (check_permission(Permission.WRITE_EXTERNAL_STORAGE) and check_permission(Permission.READ_EXTERNAL_STORAGE))
修改后的buildozer.spec配置
requirements = plyer, jnius, kivy, https://github.com/kivymd/kivymd/archive/master.zip ... ... # (list) Permissions android.permissions = android.permission.INTERNET, android.permission.WRITE_EXTERNAL_STORAGE, android.permission.READ_EXTERNAL_STORAGE, android.permission.MANAGE_EXTERNAL_STORAGE
内容的提问来源于stack exchange,提问作者Lőránt Nováki
相关产品推荐
相关产品推荐

