![](/img/trans.png)
[英]How to get Access to External Storage in Android 10 (Android Q)?
[英]Restricted access to external storage, android < 10
我想在应用Scoped storage
的 android < 10 中的用户存储中读取和写入文件,出于某种原因,我无法为此使用隐私友好的存储访问权限,因此我需要使用All files access
权限。 为了获得许可,我使用Permission Handler
程序 package 并调用Permission.manageExternalStorage.request()
,如下所示:
Future<void> _requestManageExternalStorage() async {
if(!await Permission.manageExternalStorage.isGranted) {
await Permission.manageExternalStorage.request();
}
}
las,一旦我调用该方法,这就是我得到的: 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
中,据说,权限处理程序给出的 output 几乎是无意义的。 我尝试使用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>
非常感谢任何见解或帮助! 在 android 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
权限。
打印日志消息是因为android.permission.MANAGE_EXTERNAL_STORAGE
权限没有作为Context.getPackageInfo().requestedPermissions
API 返回的数组的一部分返回。 因此permission_handler 插件认为该权限未在AndroidManifest.xml 文件中列出。 在这种情况下,这当然不完全正确,但我的假设是 Android 会过滤掉不适用于当前 Android 版本的权限。
作为permission_handler 插件的维护者,我将确保日志消息得到更新,因此它也考虑了这个选项。
这就是我实现它的方式。 我基本上是在检查 SDK 的哪个版本是 android 设备使用的。 如果设备低于 Android 11,我们将请求基本权限。 如果设备是 android 11 或以上,那么我们也会要求管理外部存储。 我正在使用 bool 来了解设备是否获得了正确的权限。 在我的测试中,它有效。
Future<bool> getPermissions() async {
bool gotPermissions = false;
var androidInfo = await DeviceInfoPlugin().androidInfo;
var release = androidInfo.version.release; // Version number, example: Android 12
var sdkInt = androidInfo.version.sdkInt; // SDK, example: 31
var manufacturer = androidInfo.manufacturer;
var model = androidInfo.model;
print('Android $release (SDK $sdkInt), $manufacturer $model');
if (Platform.isAndroid) {
var storage = await Permission.storage.status;
if (storage != PermissionStatus.granted) {
await Permission.storage.request();
}
if (sdkInt >= 30) {
var storage_external = await Permission.manageExternalStorage.status;
if (storage_external != PermissionStatus.granted) {
await Permission.manageExternalStorage.request();
}
storage_external = await Permission.manageExternalStorage.status;
if (storage_external == PermissionStatus.granted
&& storage == PermissionStatus.granted) {
gotPermissions = true;
}
} else {
// (SDK < 30)
storage = await Permission.storage.status;
if (storage == PermissionStatus.granted) {
gotPermissions = true;
}
}
}
return gotPermissions;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.