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

Flutter移除MANAGE_EXTERNAL_STORAGE权限并合规访问WhatsApp状态文件夹

具体修改方案

一、权限替换(移除违规权限,添加合规权限)

1. 修改AndroidManifest.xml

直接删除android.permission.MANAGE_EXTERNAL_STORAGE权限,替换为以下合规权限配置:

<!-- Android 10及以下版本的基础存储读取权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- Android 13+ 专属媒体读取权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- 允许访问用户选择的媒体内容 -->
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />

同时在<application>标签内添加适配Android 10的旧存储模型配置:

<application
    ...
    android:requestLegacyExternalStorage="true">
    ...
</application>

二、适配WhatsApp状态文件夹访问逻辑

WhatsApp状态文件夹WhatsApp/Media/.Statuses是隐藏目录,Android 10及以上无法直接通过文件路径访问,必须通过MediaStore API查询获取。

1. 修改数据获取Provider(替换原文件读取逻辑)

替换原直接读取目录的代码,改用MediaStore查询状态文件:

import 'dart:io';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter/services.dart';
import 'package:device_info_plus/device_info_plus.dart';

// 请求对应存储权限
Future<bool> requestRequiredPermissions() async {
  if (!Platform.isAndroid) return true;
  
  final androidInfo = await DeviceInfoPlugin().androidInfo;
  PermissionStatus status;

  if (androidInfo.version.sdkInt >= 33) {
    // Android 13+ 请求媒体权限
    status = await Permission.photos.request();
  } else if (androidInfo.version.sdkInt >= 30) {
    // Android 11/12 请求存储权限
    status = await Permission.storage.request();
  } else {
    // Android 10及以下 请求存储权限
    status = await Permission.storage.request();
  }

  return status.isGranted;
}

// 查询WhatsApp状态媒体文件
Future<List<File>> fetchWhatsAppStatuses() async {
  final List<File> statusFiles = [];
  if (!await requestRequiredPermissions()) return statusFiles;

  // 构造MediaStore查询条件,匹配WhatsApp状态目录
  const selection = "${MediaStore.MediaColumns.RELATIVE_PATH} LIKE ?";
  const selectionArgs = ["%WhatsApp/Media/.Statuses%"];

  final cursor = await MediaStore.query(
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
    projection: [MediaStore.MediaColumns.DATA],
    selection: selection,
    selectionArgs: selectionArgs,
  );

  if (cursor != null && cursor.moveToFirst()) {
    do {
      final filePath = cursor.getString(
        cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)
      );
      final file = File(filePath);
      if (await file.exists()) statusFiles.add(file);
    } while (cursor.moveToNext());
    cursor.close();
  }

  return statusFiles;
}

2. UI展示适配

原UI逻辑无需大幅修改,只需在加载数据时调用新的查询方法,并确保先完成权限校验:

List<File> _statusList = [];

void loadStatusContent() async {
  final statuses = await fetchWhatsAppStatuses();
  setState(() => _statusList = statuses);
}

// 在initState或用户触发操作时调用loadStatusContent
@override
void initState() {
  super.initState();
  loadStatusContent();
}

三、Google Play合规要点

  • 严格限制访问范围:仅读取WhatsApp/Media/.Statuses下的文件,禁止访问其他无关存储内容
  • 明确权限用途:在应用内权限申请弹窗、隐私政策中,清晰说明权限用于读取和保存WhatsApp状态
  • 最小权限原则:Android 13+仅申请必要的媒体权限,不要额外请求多余权限

内容的提问来源于stack exchange,提问作者Alpesh Kukadiya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 00:59:53