Android 13中的存储权限 - Flutter

8
我正在使用读写权限来访问外部存储,并且为了获取权限,我正在使用权限处理程序包。

AndroidManifest.xml

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

获取用户的许可
var status = await Permission.storage.request();
if (status.isGranted) {
  Navigator.of(context).pushReplacement(
    MaterialPageRoute(builder: (context) => const Home())
  );
} else if (status.isPermanentlyDenied) {
  openAppSettings();
}

上述的权限和代码在Android版本12之前都能完美运行,但是当涉及到Android版本13时,它就无法正常工作了,它只会打开应用程序设置而不是询问权限。

1
这是因为权限已经被释放,与sdk 33相关的此权限发生了变化,如此处所述stackoverflow上的这里 - Chance
那么您的建议是在Android版本大于12的情况下,我不需要请求存储权限?我的做法是从API获取视频URL并将其保存到图库中,这样我需要权限吗?@Chance - shakti goyal
非常奇怪,你还在问这个问题,因为你已经知道权限是隐含给出的。为什么不自己测试一下呢?而且你也没有说你要访问哪个存储位置。 - blackapps
刚测试过了!在 Android 版本 13 中无需请求权限 :) @blackapps - shakti goyal
你应该检查权限,但是在权限处理程序中存在一个错误,它会以被拒绝的状态检查sdk 33中的权限,正如他们的问题描述 - Chance
6个回答

9

步骤 1

在 Android 清单中添加权限

<!-- Required only if your app targets Android 13 or higher. -->
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
     android:maxSdkVersion="33" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" 
       android:maxSdkVersion="33"  />
<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"/>

步骤 2

var status = await Permission.manageExternalStorage.request();
if (status.isGranted) {
  Navigator.of(context).pushReplacement(
    MaterialPageRoute(builder: (context) => const Home())
  );
} else if (status.isPermanentlyDenied) {
  openAppSettings();
}

enter image description here


我们如何指定在权限对话框中使用的图像? - Jean-Pierre Schnyder
1
谢谢 - <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="33" /> - 我只是添加了 android:maxSdkVersion="33",现在它可以正常工作了。 - DevPankajPatel
@DevPankajPatel maxSdkVersion="33" or maxSdkVersion="32" ??? - undefined
@mohammed shamseerpv maxSdkVersion="33" 还是 maxSdkVersion="32" ??? - undefined
@mohammed shamseerpv 访问PDF、Excel、PPT和音频文件应该具备哪些权限? - undefined
@KJEjava48 在更新了Android更新存储请求权限策略之后,maxSdkVersion="32" 对我起作用了。在更新策略之前,33 也正常工作。 - undefined

9

适用于 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_AUDIO"/>

permission_handler(请求)

await Permission.photos.request();

无法工作,已使用 permission_handler: ^8.1.6 - Shahadat Hossain
2
唯一解决方案对我起了作用,谢谢! - undefined
1
唯一对我有效的解决方案,谢谢! - stavros.3p
我们如何阅读PDF文件? - undefined
@Usama 对于访问诸如PDF、Excel、PPT和音频文件之类的文件,应该设置什么样的权限? - undefined

6

如果您使用 targetSdk 版本 33,则使用以下代码。

bool permissionStatus;
final deviceInfo = await DeviceInfoPlugin().androidInfo;
    
if (deviceInfo.version.sdkInt > 32) {
    permissionStatus = await Permission.photos.request().isGranted;
} else {
    permissionStatus = await Permission.storage.request().isGranted;
}

使用此权限清单文件:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

访问文件(如PDF、Excel、PPT、音频文件)需要什么样的权限? - undefined

0
将以下代码添加到 AndroidManifest.xml 文件以获取权限:
<!--for android 13 and above-->
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <!-- For Images-->
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEOS" /> <!-- For video-->
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <!-- For Audio-->

<!-- for below android 13-->
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

将以下依赖项添加到pubspec.yaml中。
device_info_plus: ^version

将以下代码片段添加进去:
Future<void> _getStoragePermission() async {
    DeviceInfoPlugin plugin = DeviceInfoPlugin();
    AndroidDeviceInfo android = await plugin.androidInfo;
       if (android.version.sdkInt < 33) {
          if (await Permission.storage.request().isGranted) {
             setState(() {
               permissionGranted = true;
             });
          } else if (await Permission.storage.request().isPermanentlyDenied) {
             await openAppSettings();
          } else if (await Permission.audio.request().isDenied) {
             setState(() {
               permissionGranted = false;
             });
          }
        } else {
           if (await Permission.photos.request().isGranted) {
                setState(() {
                   permissionGranted = true;
                });
           } else if (await Permission.photos.request().isPermanentlyDenied) {
               await openAppSettings();
           } else if (await Permission.photos.request().isDenied) {
               setState(() {
                   permissionGranted = false;
               });
         }
      }
}

愉快的编码!


访问文件,如PDF、Excel、PPT和音频文件应该具备哪些权限? - undefined
你可以使用删除音频权限,或者简单地使用上述相同的代码。 这可能会起作用! - undefined
确定要删除音频吗?还是说要记录而不是录音? - undefined
就您的文件而言,只需提供访问PDF、Excel、PPT和音频等文件的存储权限即可。如果您想录制音频(使用麦克风),则需要请求音频权限。 - undefined
你是说在 Android 版本 sdkInt > 32 上,存储权限可以用于访问诸如 PDF、Excel、PPT 和音频文件之类的文件? - undefined
嗨 @KJEjava48,存储权限将在33 sdk以下起作用,而对于33及以上的版本,请参考https://developer.android.com/about/versions/13/behavior-changes-13。 - undefined

0
在最近的开发者版本中,对于文件而言不再需要请求权限,因此您可以直接使用FilePicker来访问存储。但是您需要在清单文件中指定以下权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

而且,对于这个权限处理程序包来说存在缺陷,它总是返回拒绝状态


0
我在经过大量的搜索和测试后找到了适用于任何Android版本的方法。
自Android 13发布后,出现了一个重大变化。
在Android 13+上,请求"storage"权限总是返回"denied"。我该怎么办?
在Android上,Permission.storage权限与Android的READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限相关联。从Android 10(API 29)开始,READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限已被标记为弃用,并且自Android 13(API 33)起已完全移除/禁用。
如果您的应用程序需要访问媒体文件,Google建议使用READ_MEDIA_IMAGES、READ_MEDIA_VIDEOS或READ_MEDIA_AUDIO权限。可以使用Permission.photos、Permission.videos和Permission.audio来请求这些权限。要请求这些权限,请确保android/app/build.gradle文件中的compileSdkVersion设置为33。
如果您的应用程序需要访问Android的文件系统,可以请求MANAGE_EXTERNAL_STORAGE权限(使用Permission.manageExternalStorage)。自Android 11(API 30)起,MANAGE_EXTERNAL_STORAGE权限被视为高风险或敏感权限。因此,如果您打算通过Google Play商店发布应用程序,必须声明使用这些权限。了解更多... 在您的清单文件中添加以下内容:
    <!-- for below android 13-->
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- for above 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_AUDIO" />

    <!-- InternetPermission -->

在标签中还要添加android:requestLegacyExternalStorage="true"这一行。
        <application
        android:requestLegacyExternalStorage="true" // add here
        android:label="iFlutter"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher"
        android:enableOnBackInvokedCallback="true"
    >

注意

在这里,我们在Android版本13及以下的清单中管理请求,但问题仍然是如何识别和使用所有设备(任何Android版本)的权限。

在这里,我们使用了最新版本的permission_handlerdevice_info_plus

现在我创建了一个方法,可以处理任何Android版本的存储权限。

Future<bool> storagePermission() async {
  final DeviceInfoPlugin info = DeviceInfoPlugin(); // import 'package:device_info_plus/device_info_plus.dart';
  final AndroidDeviceInfo androidInfo = await info.androidInfo;
  debugPrint('releaseVersion : ${androidInfo.version.release}');
  final int androidVersion = int.parse(androidInfo.version.release);
  bool havePermission = false;

  if (androidVersion >= 13) {
    final request = await [
      Permission.videos,
      Permission.photos,
      //..... as needed
    ].request(); //import 'package:permission_handler/permission_handler.dart';

    havePermission = request.values.every((status) => status == PermissionStatus.granted);
  } else {
    final status = await Permission.storage.request();
    havePermission = status.isGranted;
  }

  if (!havePermission) {
    // if no permission then open app-setting
    await openAppSettings();
  }

  return havePermission;
}

如何使用

         // Your button
         onPressed: () async {
            final permission = await storagePermission();
            debugPrint('permission : $permission');
          },

希望这能对你有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接