dart Flutter[Android]:无法使用管理外部存储权限发布应用程序

nzk0hqpo  于 9个月前  发布在  Flutter
关注(0)|答案(4)|浏览(168)

我们需要允许用户在外部存储器中存储文件,为此,我们在应用程序中使用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 Play控制台拒绝了应用程序,并拒绝了以下拒绝(我们还提交了manage_storage权限的原因)。


的数据

balp4ylt

balp4ylt1#

我找到了解决这个问题的方法
在Android级别下正确测试小于11或大于11
首先请检查这是你的onpressd按钮上的android设备像这样

if(Platform.isAndroid)
{
  downloadAndSavePDF('your network link');
}

字符串
=> then方法

Future<void> downloadAndSavePDF(String pdfUrl, String fileName) async {
final response = await http.get(Uri.parse(pdfUrl));
if (response.contentLength == 0) {
  return Future.value(null);
}
try {
  if (response.statusCode == 200) {
    // Get the downloads directory
    Directory downloadsDirectory =
        Directory('/storage/emulated/0/Download/');
    final File file = File('${downloadsDirectory.path}/$fileName');
    if (file.existsSync()) {
      Navigator.pop(context);
      CustomSnakeBar(errorMessage: 'File already downloaded')
          .snakeBar(context);
      return;
    }
    // Write the PDF content to the file
    await file.writeAsBytes(response.bodyBytes);
    Navigator.pop(context);
    CustomSnakeBar(
            errorMessage: 'PDF downloaded', colorText: ConstColor.green)
        .snakeBar(context);
  } else {
    CustomSnakeBar(errorMessage: ConstString.somethingWentWrong)
        .snakeBar(context);
  }
} catch (e) {
  Navigator.pop(context);
  CustomSnakeBar(errorMessage: ConstString.somethingWentWrong)
      .snakeBar(context);
}
}

yqkkidmi

yqkkidmi2#

我在我的项目中发现并应用了上述问题的以下解决方案。
1.我们必须使用SAF(Storage Access Framework)来代表存储权限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;
    }
  }

字符串

cbjzeqam

cbjzeqam3#

如果不是一个需要访问设备外部存储的应用程序(例如防病毒应用程序),并且您想在Flutter中下载文件,您可以在安装过程中使用path_provider包通过Android使用您的应用程序特定的目录提供程序。

final response = await http.get(Uri.parse(URL!));
final appDir = await getApplicationDocumentsDirectory();
File file = File(appDir.path + '/${filename}');
try {
  await file.writeAsBytes(response.bodyBytes);
  print('success');
} catch (e) {
  print(e.toString());
}

字符串
或者你可以使用dio包来下载文件,它管理你创建文件所需的一切。

try {
  Response response = await Dio().download(
    downloadURL!,
    appDir.path + '/${filename}',
    onReceiveProgress: (received, total) {
      // You can handle download progress here
      print('Received: $received, Total: $total');
    },
  );
  print('success');
} catch (e) {
  print('Error: $e');
}

46scxncf

46scxncf4#

我们需要允许用户在外部存储器中存储文件,为此,我们在应用程序中使用MANAGE_EXTERNAL_REPORT权限。
您不需要该权限就可以在公共目录(如Download、Documents、DCIM、Pictures等)中创建子目录。
在这些目录和子目录中创建文件也不需要该权限。

相关问题