Kivy安卓应用读取Download目录图片遇Errno 13权限拒绝问题
解决Kivy安卓应用读取外部存储权限拒绝问题
问题根源
你的问题核心在于Android版本的权限机制差异:
- Android 10(API 29)引入分区存储,即使声明了
READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE,直接访问公共目录(如Download)也会被限制,除非启用兼容模式。 - 部分Android 12设备厂商严格执行分区存储规则,而摩托罗拉设备可能默认兼容旧版权限逻辑。
- 代码存在权限请求后未校验授予状态、硬编码路径、全局变量未初始化等问题,进一步触发权限错误。
分步解决方案
1. 启用Android 10兼容模式(临时快速修复)
在buildozer.spec中添加兼容配置,让应用在Android 10上绕过分区存储限制:
android.extra_manifest_entries = <application android:requestLegacyExternalStorage="true" />
2. 正确处理权限请求与校验
当前代码仅发起权限请求但未确认用户是否授予,需添加回调检查权限状态:
from android.permissions import request_permissions, Permission, check_permission class Main(MDApp): def build(self): Builder.load_string(kv) return Demo() def on_start(self): if platform == 'android': request_permissions( [Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE], self.on_permissions_result ) def on_permissions_result(self, permissions, grants): for perm, grant in zip(permissions, grants): if not grant: self.root.ids.inp1.text = f"需要{perm}权限才能运行" return # 权限全部授予后再执行文件操作
3. 避免硬编码路径,用系统API获取Download目录
不要直接写/storage/emulated/0/Download/,通过系统API适配不同设备:
def encrypt(self): try: text = self.ids.inp1.text + "!" time_now = datetime.now().strftime("%Y%m%d_%H%M%S") # 用with语句自动管理文件资源 with open(self.choice_picture, 'rb') as start_bmp: if platform == "android": from jnius import autoclass Environment = autoclass('android.os.Environment') download_dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() encode_path = f"{download_dir}/encoded_{time_now}.bmp" with open(encode_path, 'wb') as encode_bmp: encode_bmp.write(start_bmp.read()) self.ids.inp1.text = f"Файл збережено у папку Download під назвою: encoded_{time_now}.bmp" except Exception as e: self.ids.inp1.text = str(e)
4. 修复代码其他问题
- 替换全局变量为实例变量:将
global choice_picture改为self.choice_picture = selection[0],后续用self.choice_picture访问。 - 确保
decrypt方法同步处理权限校验和路径逻辑,避免同样的权限错误。
长期适配方案(分区存储规范)
如果要彻底适配Android 10+,建议使用**存储访问框架(SAF)**或MediaStore API读写公共目录文件。plyer的filechooser已基于SAF实现文件选择,保存文件时也可通过SAF让用户选择保存位置,避免直接访问路径。
内容的提问来源于stack exchange,提问作者VitaliiShpinat
相关产品推荐
相关产品推荐

