我需要打开一个文件,这是我的应用程序中的附件,这些文件可以是任何类型的真的,图像,视频,PDF,Excel文件. Android 13拥有READ_MEDIA_IMAGES、READ_MEDIA_VIDEO和READ_MEDIA_AUDIO的权限,可以使用permission_handler请求这些权限:[Permission.photos, Permission.videos, Permission.audio].request()
之后我可以用open_file包从通知中打开下载的文件:OpenFile.open(path)
但是当我试图打开一个PDF文件时,它就是不起作用。它给了我一个错误:* 权限被拒绝:android.permission.MANAGE_EXTERNAL_Flutter*
该权限在设置中被永久拒绝,这对用户来说并不直观,每当我需要从通知中打开文件时,就会将他发送到应用程序。另外,我读到here,我不能把它在清单,因为它将被拒绝的播放商店。
如果你能帮助我,下面是代码:
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:open_file/open_file.dart';
import 'package:pagedesk/data/model/ticket/attachemnt_item.dart';
import 'package:pagedesk/data/network/firebase_api.dart';
import 'package:pagedesk/utils/Utils.dart';
import 'package:pagedesk/view_model/ticket_attachemnts_view_model.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
class Notifications {
int maxProgress = 5;
bool isCompleted = false;
Future getDownloadNotification(
AttachemntItem item,
String downloadingText,
String downloadCompletedText,
String downoadFaildMessage,
String cantOpenFailMessage,
TicketAttachemntsViewModel viewModel) async {
final AndroidNotificationDetails androidNotificationDetails =
AndroidNotificationDetails(
'name',
'name',
channelDescription: 'progress channel description',
channelShowBadge: false,
importance: Importance.max,
priority: Priority.high,
onlyAlertOnce: true,
showProgress: false,
);
final NotificationDetails notificationDetails =
NotificationDetails(android: androidNotificationDetails);
String newPath = "";
Directory directory;
try {
if (Platform.isAndroid) {
if (await requestStoragePermissions()) {
directory = (await getExternalStorageDirectory())!;
print(directory);
List<String> paths = directory.path.split("/");
for (int x = 1; x < paths.length; x++) {
String folder = paths[x];
if (folder != "Android") {
newPath += "/$folder";
} else {
break;
}
}
newPath = "$newPath/Download";
directory = Directory(newPath);
} else {
return;
}
} else {
if (await _requestPermission(Permission.storage)) {
directory = await getApplicationDocumentsDirectory();
} else {
return;
}
}
if (!await directory.exists()) {
await directory.create(recursive: true);
}
String filename = item.name;
String path = directory.path;
print('FILENAME: $filename');
print('OATH: $path');
File file = File('$path/$filename');
if (await file.exists()) {
int suffix = 1;
String newFileName;
while (await file.exists()) {
newFileName =
'${filename.replaceAll(RegExp(r'\..+'), '')}($suffix)${filename.substring(filename.lastIndexOf('.'))}';
file = File('$path/$newFileName');
suffix++;
}
} else {
print("File doesn't exist");
}
FirebaseApi.localNotifications.show(
item.id,
item.name,
isCompleted ? downloadCompletedText : downloadingText,
notificationDetails,
payload: newPath);
viewModel.getAttachment(item).then((value) => {
if (value != null)
{
file.writeAsBytes(value),
isCompleted = true,
FirebaseApi.localNotifications.cancel(item.id),
FirebaseApi.localNotifications.show(item.id, item.name,
downloadCompletedText, notificationDetails,
payload: file.path)
}
else
{
isCompleted = false,
FirebaseApi.localNotifications.cancel(item.id),
FirebaseApi.localNotifications.show(item.id, item.name,
downoadFaildMessage, notificationDetails,
payload: null)
}
});
} catch (e) {
print('ERROR');
}
}
}
void openFile(String path, String cantOpenFileMessage) async {
try {
final result = await OpenFile.open(path);
if (result.type == ResultType.done) {
print('File opened successfully');
} else if (result.type == ResultType.noAppToOpen) {
Utils.toastMessage(cantOpenFileMessage);
} else {
Utils.toastMessage("Can't open file throgh this app.");
}
} catch (e) {
print('Error opening file: $e');
}
}
Future<bool> _requestPermission(Permission permission) async {
if (await permission.isGranted) {
return true;
} else if (await permission.isPermanentlyDenied) {
openAppSettings();
return false;
} else {
var result = await permission.request();
if (result == PermissionStatus.granted) {
return true;
}
}
return false;
}
Future<bool> requestStoragePermissions() async {
List<Permission> permissions = [];
final deviceInfo = await DeviceInfoPlugin().androidInfo;
if (deviceInfo.version.sdkInt > 32) {
permissions = [Permission.photos, Permission.videos, Permission.audio];
} else {
permissions = [Permission.storage];
}
Map<Permission, PermissionStatus> statuses = await permissions.request();
return !statuses.containsKey(false);
}
清单权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<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条答案
按热度按时间ezykj2lf1#
我很确定(不是100%),因为这是一个默认拒绝的新权限,你需要让用户通过设置手动更改它,即使它对用户来说并不直观,就像你说的。
我不知道你是否看到过你可以通过编程打开设置页面,这样用户就更容易了。
不幸的是,我不认为有比这更好的解决方案。
ukdjmx9f2#
现在,如果你说你的应用程序正在下载数据并为它自己创建一个文件,那么你不需要任何权限在Android 13+设备上这样做。当然也不是管理外部存储。
一旦您的应用创建并写入了文件,它将自动允许使用相同的路径读取文件。