Kivy安卓应用存储访问权限被拒问题求助
Kivy访问安卓存储权限拒绝问题
问题详情
之前使用Kivy 2.0.0及Buildozer 1.5以下版本时,访问安卓存储功能正常。现在通过android.storage库的primary_external_storage_path()方法获取存储路径/storage/emulated/0/,调用os.mkdir(os.path.join(self.primary_ext_storage, "TestKivy"))创建文件夹时,即使应用首次启动已授权存储访问,点击按钮仍崩溃,报错:
PermissionError: [Errno 13] Permission denied: '/storage/emulated/0/TestKivy'
尝试在Downloads等公共目录创建文件夹也出现相同错误。
设备参数
- 小米Mi 9T
- MIUI Global 12.0.5 Stable
- Android 10 QKQ1.190825.002
- Buildozer 1.5.0
buildozer.spec配置
[app] # (str) Title of your application title = My Application # (str) Package name package.name = myapp # (str) Package domain (needed for android/ios packaging) package.domain = org.test # (str) Source code where the main.py live source.dir = . # (list) Source files to include (let empty to include all the files) source.include_exts = py,png,jpg,kv,atlas # (str) Application versioning (method 1) version = 0.1 # (list) Application requirements # comma separated e.g. requirements = sqlite3,kivy requirements = python3,kivy # (list) Supported orientations # Valid options are: landscape, portrait, portrait-reverse or landscape-reverse orientation = portrait # # OSX Specific # # # author = © Copyright Info # change the major version of python used by the app osx.python_version = 3 # Kivy version to use osx.kivy_version = 1.9.1 # # Android specific # # (bool) Indicate if the application should be fullscreen or not fullscreen = 0 # (list) Permissions android.permissions = android.permission.WRITE_EXTERNAL_STORAGE, android.permission.READ_EXTERNAL_STORAGE # (list) The Android archs to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64 android.archs = arm64-v8a, armeabi-v7a # (bool) enables Android auto backup feature (Android API >=23) android.allow_backup = True # # iOS specific # # (str) Path to a custom kivy-ios folder #ios.kivy_ios_dir = ../kivy-ios # Alternately, specify the URL and branch of a git checkout: ios.kivy_ios_url = https://github.com/kivy/kivy-ios ios.kivy_ios_branch = master # Another platform dependency: ios-deploy # Uncomment to use a custom checkout #ios.ios_deploy_dir = ../ios_deploy # Or specify URL and branch ios.ios_deploy_url = https://github.com/phonegap/ios-deploy ios.ios_deploy_branch = 1.10.0 # (bool) Whether or not to sign the code ios.codesign.allowed = false [buildozer] # (int) Log level (0 = error only, 1 = info, 2 = debug (with command output)) log_level = 2 # (int) Display warning if buildozer is run as root (0 = False, 1 = True) warn_on_root = 1
main.py代码
import os from kivy.utils import platform # Import kivy modules from kivy.app import App from kivy.uix.button import Button # Create app class HelloApp(App): def build(self): self.btn = Button(text="Hello World") self.btn.bind(on_press=self.on_press_button) return self.btn def on_start(self): if platform == "android": # Import necessary modules for Android permissions from android.storage import primary_external_storage_path from android.permissions import request_permissions, Permission # Request storage access permissions request_permissions([ Permission.WRITE_EXTERNAL_STORAGE, Permission.READ_EXTERNAL_STORAGE ]) # Set the default storage path depending on the device self.primary_ext_storage = primary_external_storage_path() if platform == "android" else os.environ["HOME"] def on_press_button(self, instance): # Create folder in the default storage path os.mkdir(os.path.join(self.primary_ext_storage, "TestKivy")) # Run app if __name__ == "__main__": HelloApp().run()
解决办法
适配Android 10存储策略
Android 10引入了分区存储机制,即使申请了WRITE_EXTERNAL_STORAGE权限,也无法直接在根目录创建文件夹。需要在buildozer.spec的Android配置区域添加:android.extra_manifest_placeholders = android:requestLegacyExternalStorage="true"让应用使用旧版存储访问模式。
等待权限授权完成再操作
原代码中request_permissions是异步执行的,可能权限还未通过就触发了文件夹创建操作。修改代码监听权限申请结果,确认授权后再执行存储操作:def on_start(self): if platform == "android": from android.storage import primary_external_storage_path from android.permissions import request_permissions, Permission def on_permission_result(permissions, grants): if all(grants): self.primary_ext_storage = primary_external_storage_path() else: # 处理权限被拒绝的逻辑 pass request_permissions([ Permission.WRITE_EXTERNAL_STORAGE, Permission.READ_EXTERNAL_STORAGE ], on_permission_result) else: self.primary_ext_storage = os.environ["HOME"] def on_press_button(self, instance): if not hasattr(self, 'primary_ext_storage'): return folder_path = os.path.join(self.primary_ext_storage, "TestKivy") if not os.path.exists(folder_path): os.mkdir(folder_path)检查MIUI特殊权限
小米MIUI系统可能存在额外存储权限限制,进入手机设置-应用管理-目标应用-权限管理,确认“存储”权限已完全开启,无其他限制。
内容的提问来源于stack exchange,提问作者felinx94
相关产品推荐
相关产品推荐

