android - 限制访问外部存储,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 中测试
解决方案
该android.permission.MANAGE_EXTERNAL_STORAGE
权限是在 Android 11 (API 30) 中引入的,因此在 Android 10 或更低版本上不支持(请参阅官方文档)。
permission_handler 插件返回PermissionStatus.restricted
是因为它不知道如何处理 Android 10 及更低版本的权限。在 Android 10 及更低版本的情况下,只需限制请求android.permission.READ_EXTERNAL_STORAGE
和android.permission.WRITE_EXTERNAL_STORAGE
权限。
打印日志消息是因为权限未作为APIandroid.permission.MANAGE_EXTERNAL_STORAGE
返回的数组的一部分返回。Context.getPackageInfo().requestedPermissions
因此,permission_handler 插件认为该权限未在 AndroidManifest.xml 文件中列出。在这种情况下,这当然不完全正确,但是我的假设是 Android 过滤掉了不适用于当前 Android 版本的权限。
作为 permission_handler 插件的维护者,我将确保日志消息得到更新,因此它也会考虑这个选项。
推荐阅读
- recursion - 给出不同结果的类似 Python 代码 - 生成给定大小的子集
- javascript - 我们如何使这个 JS ES6+ 高阶函数变得干净?
- javascript - 如何在反应中绘制数组的最后 90 个元素
- react-native - 如何从 react-native-modals 在模态的覆盖区域中添加组件
- python-2.7 - Maya:将顶点蒙皮权重复制粘贴到不同命名空间中的对象
- php - 调用数组上的成员函数 links()
- python-3.x - 如何在forms.ChoiceField中从views.py中传递选择?
- elasticsearch - Elasticsearch 重定位分片卡住
- c++ - 访问部分是否对 C++ 数据模型中位字段的大小有影响?
- amazon-web-services - Terraform - 什么是空提供者?