Flet安卓应用读取SD卡文件时遭遇Permission Denied (Error 13)错误求助
Flet安卓应用读取SD卡文件时遭遇Permission Denied (Error 13)错误求助
嘿,我来帮你搞定这个权限被拒的问题~ 安卓系统对外部存储的管控一直挺严格的,尤其是从Android 6.0开始,危险权限得动态申请,再加上高版本的分区存储机制,直接硬编码路径访问文件很容易踩坑。结合你给出的代码片段,我给你梳理几个解决步骤:
1. 补全并修正权限申请的代码
你代码里的ft.Permissi应该是打错了,Flet对应的权限处理是调用页面的权限接口。你得先主动申请读取外部存储的权限,不能默认系统会自动授权。修改后的代码大概是这样:
import flet as ft import os FILE_PATH = "/sdcard/Documents/personnel_utf8.txt" def main(page: ft.Page): page.scroll = ft.ScrollMode.ADAPTIVE page.appbar = ft.AppBar(title=ft.Text("PermissionHandler Tests")) # 定义需要申请的存储读取权限 read_storage_perm = ft.Permission.READ_EXTERNAL_STORAGE async def check_and_request_permission(e): # 先检查权限状态 status = await page.permissions.get_status(read_storage_perm) if status != ft.PermissionStatus.GRANTED: # 权限没拿到,主动申请 result = await page.permissions.request_async([read_storage_perm]) if result[read_storage_perm] == ft.PermissionStatus.GRANTED: page.add(ft.Text("权限申请成功,尝试读取文件...")) read_file() else: page.add(ft.Text("读取存储权限被拒绝,无法访问文件!")) else: # 已经有权限,直接读文件 read_file() def read_file(): try: with open(FILE_PATH, "r", encoding="utf-8") as f: content = f.read() page.add(ft.Text("文件内容:")) page.add(ft.Text(content)) except Exception as e: page.add(ft.Text(f"读取失败:{str(e)}")) # 加个按钮触发权限检查和读取操作 page.add(ft.ElevatedButton("读取文件", on_click=check_and_request_permission)) page.update() ft.app(main)
2. 配置AndroidManifest.xml的权限声明
光靠代码申请还不够,得先在安卓的清单文件里声明权限。你可以找到Flet项目编译后生成的Android项目中的AndroidManifest.xml,添加以下内容:
<!-- 声明读取外部存储权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- 如果适配Android 10(API 29)及以上,添加这个过渡属性,临时绕过分区存储限制 --> <application android:requestLegacyExternalStorage="true" ... <!-- 保留原有其他属性 --> >
3. 调整上传文件的权限
你用adb push上传的文件,默认权限可能只有root用户能访问,普通应用没权限读取。可以在电脑上执行这个adb命令修改文件权限:
adb shell chmod 666 /sdcard/Documents/personnel_utf8.txt
这个命令会让所有用户都能读写该文件,确保你的应用能正常访问。
4. 长期适配建议(Android 11+)
如果你的目标是Android 11及以上系统,官方推荐用分区存储(Scoped Storage),硬编码路径访问会越来越受限。你可以用Flet的FilePicker组件让用户手动选择文件,既符合系统规范,也能避免权限问题,代码示例:
import flet as ft def main(page: ft.Page): page.scroll = ft.ScrollMode.ADAPTIVE page.appbar = ft.AppBar(title=ft.Text("文件读取测试")) async def pick_and_read_file(e): # 调用文件选择器 result = await page.file_picker.pick_files(allow_multiple=False) if result: selected_file = result.files[0] try: with open(selected_file.path, "r", encoding="utf-8") as f: content = f.read() page.add(ft.Text(f"读取到文件内容:")) page.add(ft.Text(content)) except Exception as e: page.add(ft.Text(f"读取失败:{str(e)}")) # 初始化文件选择器并添加到页面 page.file_picker = ft.FilePicker() page.add(ft.ElevatedButton("选择文件并读取", on_click=pick_and_read_file)) page.update() ft.app(main)
你可以先试前三个步骤快速解决当前问题;如果要做长期适配,再考虑FilePicker的方案~
备注:内容来源于stack exchange,提问作者leobip
相关产品推荐
相关产品推荐

