Flutter[Android]:无法发布具有管理外部存储权限的应用程序
Flutter[Android]: Not able to release App with Manage External Storage Permission
我们需要允许用户在外部存储中存储文件,为此,我们在应用程序中使用 MANAGE_EXTERNAL_STORAGE
权限。
理想情况下,对于 android SDK 版本 30 及更高版本,我们使用 Permission.manageExternalStorage
,对于低于 30 的 android SDK 版本使用 Permission.storage
,如下面的代码所示
// This func is added to access scope storage to export csv files
static Future<bool> externalStoragePermission(BuildContext context) async {
final androidVersion = await DeviceInfoPlugin().androidInfo;
if ((androidVersion.version.sdkInt ?? 0) >= 30) {
return await checkManageStoragePermission(context);
} else {
return await checkStoragePermission(context);
}
}
static Future<bool> checkManageStoragePermission(BuildContext context) async {
return (await Permission.manageExternalStorage.isGranted ||
await Permission.manageExternalStorage.request().isGranted);
}
static Future<bool> checkStoragePermission(BuildContext context,
{String? storageTitle, String? storageSubMessage}) async {
if (await Permission.storage.isGranted ||
await Permission.storage.request().isGranted) {
return true;
} else {
openBottomSheet(
title: storageTitle ?? Str.of(context).storagePermissionRequired,
message: storageSubMessage ?? Str.of(context).storageSubMessage,
).show(context);
return false;
}
}
通过上述实施,开发和内部发布时一切正常,但 Google 游戏控制台拒绝了具有以下拒绝的应用程序(我们还提交了 manage_storage 的原因许可)。
We need to allow users to store files in the external storage and for the same, we use MANAGE_EXTERNAL_STORAGE permission in our application.
您不需要该权限即可在 public 目录(如下载、文档、DCIM、图片等)中创建自己的子目录。
此外,您不需要该权限即可在这些目录和子目录中创建文件。
我在我的项目中找到并应用了以下解决方案来解决上述问题。
- 我们必须使用 SAF(Storage Access Framework) on behalf of the storage permission shared_storage 这将允许我们授予共享存储中特定目录的权限,我们可以将文件存储在那里。我还在下面添加了相同的代码示例。
Future<void> exportFile({
required String csvData,
required String fileName,
}) async {
Uri? selectedUriDir;
final pref = await SharedPreferences.getInstance();
final scopeStoragePersistUrl = pref.getString('scopeStoragePersistUrl');
// Check User has already grant permission to any directory or not
if (scopeStoragePersistUrl != null &&
await isPersistedUri(Uri.parse(scopeStoragePersistUrl)) &&
(await exists(Uri.parse(scopeStoragePersistUrl)) ?? false)) {
selectedUriDir = Uri.parse(scopeStoragePersistUrl);
} else {
selectedUriDir = await openDocumentTree();
await pref.setString('scopeStoragePersistUrl', selectedUriDir.toString());
}
if (selectedUriDir == null) {
return false;
}
try {
final existingFile = await findFile(selectedUriDir, fileName);
if (existingFile != null && existingFile.isFile) {
debugPrint("Found existing file ${existingFile.uri}");
await delete(existingFile.uri);
}
final newDocumentFile = await createFileAsString(
selectedUriDir,
mimeType: AppConstants.csvMimeTypeWhileExport,
content: csvData,
displayName: fileName,
);
return newDocumentFile != null;
} catch (e) {
debugPrint("Exception while create new file: ${e.toString()}");
return false;
}
}
我们需要允许用户在外部存储中存储文件,为此,我们在应用程序中使用 MANAGE_EXTERNAL_STORAGE
权限。
理想情况下,对于 android SDK 版本 30 及更高版本,我们使用 Permission.manageExternalStorage
,对于低于 30 的 android SDK 版本使用 Permission.storage
,如下面的代码所示
// This func is added to access scope storage to export csv files
static Future<bool> externalStoragePermission(BuildContext context) async {
final androidVersion = await DeviceInfoPlugin().androidInfo;
if ((androidVersion.version.sdkInt ?? 0) >= 30) {
return await checkManageStoragePermission(context);
} else {
return await checkStoragePermission(context);
}
}
static Future<bool> checkManageStoragePermission(BuildContext context) async {
return (await Permission.manageExternalStorage.isGranted ||
await Permission.manageExternalStorage.request().isGranted);
}
static Future<bool> checkStoragePermission(BuildContext context,
{String? storageTitle, String? storageSubMessage}) async {
if (await Permission.storage.isGranted ||
await Permission.storage.request().isGranted) {
return true;
} else {
openBottomSheet(
title: storageTitle ?? Str.of(context).storagePermissionRequired,
message: storageSubMessage ?? Str.of(context).storageSubMessage,
).show(context);
return false;
}
}
通过上述实施,开发和内部发布时一切正常,但 Google 游戏控制台拒绝了具有以下拒绝的应用程序(我们还提交了 manage_storage 的原因许可)。
We need to allow users to store files in the external storage and for the same, we use MANAGE_EXTERNAL_STORAGE permission in our application.
您不需要该权限即可在 public 目录(如下载、文档、DCIM、图片等)中创建自己的子目录。
此外,您不需要该权限即可在这些目录和子目录中创建文件。
我在我的项目中找到并应用了以下解决方案来解决上述问题。
- 我们必须使用 SAF(Storage Access Framework) on behalf of the storage permission shared_storage 这将允许我们授予共享存储中特定目录的权限,我们可以将文件存储在那里。我还在下面添加了相同的代码示例。
Future<void> exportFile({
required String csvData,
required String fileName,
}) async {
Uri? selectedUriDir;
final pref = await SharedPreferences.getInstance();
final scopeStoragePersistUrl = pref.getString('scopeStoragePersistUrl');
// Check User has already grant permission to any directory or not
if (scopeStoragePersistUrl != null &&
await isPersistedUri(Uri.parse(scopeStoragePersistUrl)) &&
(await exists(Uri.parse(scopeStoragePersistUrl)) ?? false)) {
selectedUriDir = Uri.parse(scopeStoragePersistUrl);
} else {
selectedUriDir = await openDocumentTree();
await pref.setString('scopeStoragePersistUrl', selectedUriDir.toString());
}
if (selectedUriDir == null) {
return false;
}
try {
final existingFile = await findFile(selectedUriDir, fileName);
if (existingFile != null && existingFile.isFile) {
debugPrint("Found existing file ${existingFile.uri}");
await delete(existingFile.uri);
}
final newDocumentFile = await createFileAsString(
selectedUriDir,
mimeType: AppConstants.csvMimeTypeWhileExport,
content: csvData,
displayName: fileName,
);
return newDocumentFile != null;
} catch (e) {
debugPrint("Exception while create new file: ${e.toString()}");
return false;
}
}