You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter SAF包权限重复请求问题求助

问题:SAF包重复请求权限(已授予权限仍弹窗)

我已阅读SAF包的官方文档,但遇到问题:即使已授予权限,每次启动应用仍会重复请求权限。推测是使用SAF处理权限时有所遗漏,求解决方案。

当前实现代码

path方法

Future<int> path() async {
  DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
  AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
  if (androidInfo.version.sdkInt >= 29) {
    Permission.storage.request();
    await saf.getDirectoryPermission(isDynamic: true);
    var isSync = await saf.sync();
    if (isSync as bool) {
      var _paths = await saf.getCachedFilesPath();
      loadImage(_paths);
    }
    return 1;
  } else {
    return 0;
  }
}

Widget build方法

@override
Widget build(BuildContext context) {
  return FutureBuilder(
      future: path(),
      builder: (BuildContext context, AsyncSnapshot<int> text) {
        if (text.connectionState == ConnectionState.waiting) {
          return const Scaffold(
            body: Center(
              child: Text("Loading....",style: TextStyle(color: Color(0xff090849),fontSize: 20),),
            ),
          );
        } else {
            return  Scaffold(
                body:  GridView.builder(
                padding: const EdgeInsets.all(3.0),
                itemCount: _paths.length,
                gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 3,
                  childAspectRatio: 3/4,
                  ), 
                itemBuilder: 
                (BuildContext context, int index) {
                  return Padding(
                    padding: const EdgeInsets.all(5.0), // Adjust the value as needed
                    child: Material(
                      borderRadius: BorderRadius.circular(10),
                      elevation: 5,
                      clipBehavior: Clip.antiAliasWithSaveLayer,
                      color: Colors.teal.withOpacity(0.9),
                      child: InkWell(
                      splashColor: Colors.teal,
                      onTap: () {
                       Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (_) => ImageView(imagePath: _paths[index], key: UniqueKey()),
                        ),
                      );
                      },
                     child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        SizedBox(
                          height: 110, 
                          child: Ink.image(
                            image: FileImage(File(_paths[index])),
                            fit: BoxFit.cover,
                          ),
                        ),
                        MaterialButton(
                          height: 10,
                          onPressed: () async {
                            saveFile(_paths[index]);
                        },child: const Text("Download",style: TextStyle(color: Colors.white),),)
                      ],
                     ),
                    ),
                   )
                  );
                 },
                ),
              );
          }
       });
   }

解决方案

问题核心是未先检查权限状态就直接发起请求,且SAF权限与普通存储权限的处理逻辑未区分。修改步骤如下:

  1. 先检查存储权限状态:请求前调用Permission.storage.status判断是否已授予,仅在未授权时发起请求
  2. 避免重复请求SAF目录权限:用saf.isPermissionGranted()检查已拥有的权限,仅在未授权时调用getDirectoryPermission
  3. 修正异步逻辑:给Permission.storage.request()添加await,确保权限请求完成后再执行后续操作

修改后的path方法示例

Future<int> path() async {
  DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
  AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
  if (androidInfo.version.sdkInt >= 29) {
    // 检查存储权限状态,未授予则请求
    final storageStatus = await Permission.storage.status;
    if (!storageStatus.isGranted) {
      await Permission.storage.request();
    }

    // 检查SAF目录权限,未授予则请求
    final hasSafPermission = await saf.isPermissionGranted();
    if (!hasSafPermission) {
      await saf.getDirectoryPermission(isDynamic: true);
    }

    var isSync = await saf.sync();
    if (isSync as bool) {
      var _paths = await saf.getCachedFilesPath();
      loadImage(_paths);
    }
    return 1;
  } else {
    return 0;
  }
}

额外提示:若使用的SAF版本支持,可通过saf.getPersistedPermission()获取已持久化的权限,进一步避免重复请求。

内容的提问来源于stack exchange,提问作者Ombeni Nade

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 19:23:25