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

Flutter应用因MANAGE_EXTERNAL_STORAGE权限遭谷歌拒审,需改用MediaStore API

解决方案:移除MANAGE_EXTERNAL_STORAGE权限并改用MediaStore API

1. 先移除违规权限

打开Flutter项目下的android/app/src/main/AndroidManifest.xml,删除这一行代码:

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />

同时确保文件中没有其他和该权限相关的配置。

2. 替换媒体文件操作逻辑(Flutter端实现)

根据功能场景,用对应插件或自定义平台通道实现MediaStore操作:

场景1:保存图片/视频到公共相册

推荐使用image_gallery_saver插件(内部已封装MediaStore逻辑):

  • 添加依赖到pubspec.yaml:
    dependencies:
      image_gallery_saver: ^2.0.3
    
  • 调用保存方法的示例代码:
    import 'package:image_gallery_saver/image_gallery_saver.dart';
    import 'dart:typed_data';
    import 'package:http/http.dart' as http;
    
    // 保存网络图片到相册
    Future<void> saveNetworkImage() async {
      final response = await http.get(Uri.parse("https://example.com/image.jpg"));
      final result = await ImageGallerySaver.saveImage(
        response.bodyBytes,
        name: "my_image",
      );
      print(result);
    }
    
    // 保存本地图片文件到相册
    Future<void> saveLocalImage(String filePath) async {
      final result = await ImageGallerySaver.saveFile(filePath);
      print(result);
    }
    

场景2:读取公共存储的媒体文件

使用media_store插件访问MediaStore中的媒体:

  • 添加依赖到pubspec.yaml:
    dependencies:
      media_store: ^1.0.0
    
  • 读取图片的示例代码:
    import 'package:media_store/media_store.dart';
    
    Future<void> loadImages() async {
      // 申请读取权限(Android 13+需申请READ_MEDIA_IMAGES)
      await MediaStore.requestPermission(PermissionType.read);
      // 获取所有图片
      final images = await MediaStore.getImages();
      for (var image in images) {
        print("图片路径:${image.path},名称:${image.displayName}");
      }
    }
    

注意:Android 13及以上版本,需在AndroidManifest.xml中添加对应细分权限:

<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_AUDIO" />

Android 12及以下版本,添加READ_EXTERNAL_STORAGE权限即可:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />

场景3:批量删除/修改媒体文件

如果需要批量操作,可通过Flutter平台通道调用Android原生代码直接操作MediaStore:

  • Flutter端代码:
    import 'package:flutter/services.dart';
    
    class MediaStoreHelper {
      static const MethodChannel _channel = MethodChannel('media_store_helper');
    
      static Future<bool> deleteMedia(String mediaId) async {
        final bool result = await _channel.invokeMethod('deleteMedia', {'mediaId': mediaId});
        return result;
      }
    }
    
  • Android端原生代码(在MainActivity中):
    import android.content.ContentResolver
    import android.content.ContentUris
    import android.net.Uri
    import android.provider.MediaStore
    import io.flutter.embedding.android.FlutterActivity
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugin.common.MethodChannel
    
    class MainActivity : FlutterActivity() {
        private val CHANNEL = "media_store_helper"
    
        override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
            super.configureFlutterEngine(flutterEngine)
            MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
                if (call.method == "deleteMedia") {
                    val mediaId = call.argument<String>("mediaId")
                    mediaId?.let {
                        val deleted = deleteMediaFromStore(contentResolver, it)
                        result.success(deleted)
                    } ?: result.error("INVALID_ARG", "Media ID is null", null)
                } else {
                    result.notImplemented()
                }
            }
        }
    
        private fun deleteMediaFromStore(resolver: ContentResolver, mediaId: String): Boolean {
            val uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mediaId.toLong())
            val rowsDeleted = resolver.delete(uri, null, null)
            return rowsDeleted > 0
        }
    }
    

3. 测试与审核准备

  • 测试不同Android版本(API 29+)的功能兼容性,确保所有文件操作都通过MediaStore完成,无直接访问根目录或非媒体目录的行为。
  • 提交审核时,在审核说明中明确说明:已移除MANAGE_EXTERNAL_STORAGE权限,所有媒体操作均使用MediaStore API实现,符合Google Play的存储政策。

内容的提问来源于stack exchange,提问作者Harjinder Bains

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 20:32:41