首页 > 解决方案 > 限制访问外部存储,android < 10

问题描述

我想在 android < 10 应用的用户存储中读取和写入文件,Scoped storage由于某种原因,我不能为此使用隐私友好的存储访问,因此我需要使用All files access权限。为了获得许可,我正在使用Permission Handler包并调用Permission.manageExternalStorage.request()如下:

Future<void> _requestManageExternalStorage() async {
  if(!await Permission.manageExternalStorage.isGranted) {
    await Permission.manageExternalStorage.request();
  }
}

唉,一旦我调用了那个方法,这就是我得到的: No permissions found in manifest for: []22

至于内的权限列表Android Manifest.xml

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

请注意,我把它放在正确的位置,/android/app/src/main/AndroidManifest.xml也就是说,权限处理程序给出的输出几乎是无意义的。我试图清理项目,flutter clean甚至创建一个新项目只是为了测试它,但它仍然未能检索到想要的权限。

我试图检查我得到的 manageExternalStorage 的当前权限状态实际上是什么:PermissionStatus.restricted

从文档 PermissionStatus.restricted 意味着:

操作系统拒绝访问请求的功能。用户无法更改此应用程序的状态,可能是由于存在家长控制等主动限制。仅在 iOS 上受支持。

由此,我只能假设操作系统被强制拒绝所有文件访问?

permission_handler: ^8.2.5在撰写本文时,我使用的是最新版本。

我用来测试的完整代码:

import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool isGranted = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'Manage External Storage Test:',
            ),
            Text(
              'Is granted: $isGranted',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _requestManageExternalStorage,
      ),
    );
  }

  Future<void> _requestManageExternalStorage() async {
    if(!await Permission.manageExternalStorage.isGranted) {
      final res = await Permission.manageExternalStorage.request();
      setState((){
        isGranted = res.isGranted;  
      });
    }
  }
}

完整的 AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.file_access_test">

    <!-- Permissions options for the `storage` group -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <!-- Permissions options for the `manage external storage` group -->
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

    <application
        android:name="io.flutter.app.FlutterApplication"
        android:icon="@mipmap/ic_launcher"
        android:label="MAKE IT DAMN WORK"
        tools:ignore="AllowBackup,GoogleAppIndexingWarning">

        <activity android:name="io.flutter.embedding.android.FlutterActivity"
            android:launchMode="singleTop"
            android:theme="@android:style/Theme.Black.NoTitleBar"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>

非常感谢任何见解或帮助!在安卓 10 中测试

标签: androidflutter

解决方案


android.permission.MANAGE_EXTERNAL_STORAGE权限是在 Android 11 (API 30) 中引入的,因此在 Android 10 或更低版本上不支持(请参阅官方文档)。

permission_handler 插件返回PermissionStatus.restricted是因为它不知道如何处理 Android 10 及更低版本的权限。在 Android 10 及更低版本的情况下,只需限制请求android.permission.READ_EXTERNAL_STORAGEandroid.permission.WRITE_EXTERNAL_STORAGE权限。

打印日志消息是因为权限未作为APIandroid.permission.MANAGE_EXTERNAL_STORAGE返回的数组的一部分返回。Context.getPackageInfo().requestedPermissions因此,permission_handler 插件认为该权限未在 AndroidManifest.xml 文件中列出。在这种情况下,这当然不完全正确,但是我的假设是 Android 过滤掉了不适用于当前 Android 版本的权限。

作为 permission_handler 插件的维护者,我将确保日志消息得到更新,因此它也会考虑这个选项。


推荐阅读