英文:
Is there any way to use MAUI FileSaver in API 33 with .NET MAUI?
问题
我正在编写一个 MAUI 应用程序,该应用程序从远程 API 获取图像,并希望将其保存到设备的存储空间中。我在 Android API 33 上遇到的问题是:
由于权限发生了变化,MAUI Community Toolkit 中的 FileSaver 类仍然要求 WRITE_EXTERNAL_STORAGE 权限,但该权限已不再存在,因此默认情况下会返回 DENIED。我看到有人提到可以降级到较低的 API,但由于 Google 对其 Play 商店政策的更改,这不是一个选项。
是否有人成功地或者知道如何在 API 33 上使用 .NET 7 使 FileSaver 正常工作,或者是否有其他方法可以保存文件以便在应用程序外部访问?
这是我的 Android 清单文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="si.stroka.signature365" android:versionName="1">
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:supportsRtl="true" android:label="Signature365 Android"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.ACCOUNT_MANAGER" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</manifest>
谢谢!
编辑:
添加了我请求 FileSaver 的源代码。对话框根本不会出现,它只会在异常中抛出 Storage permission not granted 的消息。我能够通过将目标 SDK 设置为 31 来使其工作,但对于我的应用程序来说,这不是一个选项,因为 Google Play 商店要求在 8 月份使用 SDK 33...
using var stream = new MemoryStream(Encoding.Default.GetBytes("Hello from the Community Toolkit!"));
var fileSaverResult = await FileSaver.Default.SaveAsync("test.txt", stream, token.Token);
if (fileSaverResult.IsSuccessful)
{
await Toast.Make($"The file was saved successfully to location: {fileSaverResult.FilePath}").Show(token.Token);
}
else
{
await Toast.Make($"The file was not saved successfully with error: {fileSaverResult.Exception.Message}").Show(token.Token);
}
英文:
I'm writing a MAUI app that fetches an image from a remote API and would like to save it to the device's storage. The problem I'm facing is with it working on Android API 33.
As the permissions changed, the FileSaver class from the MAUI Community Toolkit still demands the WRITE_EXTERNAL_STORAGE permission, which no longer exists, so it serves DENIED as default. I've seen people mentioning that you can downgrade to a lower API, but with Google's change to their Play store policy, this is not an option.
Has anyone managed or knows how I could get the FileSaver working on API 33 with .NET 7 or is there another way to save files so they could be accessed outside the app?
This is my Android manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="si.stroka.signature365" android:versionName="1">
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:supportsRtl="true" android:label="Signature365 Android"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.ACCOUNT_MANAGER" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</manifest>
Thanks!
Edit:
Adding source code for how I request FileSaver. The dialog doesn't appear at all, it just throws the Storage permission not granted message in the exception. I was able to get it to work setting target SDK to 31, but that isn't an option for my app with Google Play Store demanding 33 in August...
using var stream = new MemoryStream(Encoding.Default.GetBytes("Hello from the Community Toolkit!"));
var fileSaverResult = await FileSaver.Default.SaveAsync("test.txt", stream, token.Token);
if (fileSaverResult.IsSuccessful)
{
await Toast.Make($"The file was saved successfully to location: {fileSaverResult.FilePath}").Show(token.Token);
}
else
{
await Toast.Make($"The file was not saved successfully with error: {fileSaverResult.Exception.Message}").Show(token.Token);
}
答案1
得分: 1
我能够通过参考此处找到的解决方法使其工作:https://github.com/CommunityToolkit/Maui/issues/998
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:supportsRtl="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
<queries>
<intent>
<action android:name="android.intent.action.SENDTO" />
<data android:scheme="mailto" />
</intent>
</queries>
</manifest>
ContentPage或ContentView代码后台
#if ANDROID
using Android;
using Android.Content.PM;
using AndroidX.Core.App;
using AndroidX.Core.Content;
#endif
在页面或视图中使用FileSaver
// this will run for Android 33 and greater
if (DeviceInfo.Platform == DevicePlatform.Android && OperatingSystem.IsAndroidVersionAtLeast(33))
{
#if ANDROID
var activity = Platform.CurrentActivity ?? throw new NullReferenceException("Current activity is null");
if (ContextCompat.CheckSelfPermission(activity, Manifest.Permission.ReadExternalStorage) != Permission.Granted)
{
ActivityCompat.RequestPermissions(activity, new[] { Manifest.Permission.ReadExternalStorage }, 1);
}
#endif
}
var fileSaverResult = await FileSaver.Default.SaveAsync(attachment.AttachmentName, stream, cancellationToken);
英文:
I was able to get this to work by referencing a workaround found here https://github.com/CommunityToolkit/Maui/issues/998
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:supportsRtl="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
<queries>
<intent>
<action android:name="android.intent.action.SENDTO" />
<data android:scheme="mailto" />
</intent>
</queries>
</manifest>
ContentPage or ContentView code behind
#if ANDROID
using Android;
using Android.Content.PM;
using AndroidX.Core.App;
using AndroidX.Core.Content;
#endif
Using the FileSaver in your page or view
// this will run for Android 33 and greater
if (DeviceInfo.Platform == DevicePlatform.Android && OperatingSystem.IsAndroidVersionAtLeast(33))
{
#if ANDROID
var activity = Platform.CurrentActivity ?? throw new NullReferenceException("Current activity is null");
if (ContextCompat.CheckSelfPermission(activity, Manifest.Permission.ReadExternalStorage) != Permission.Granted)
{
ActivityCompat.RequestPermissions(activity, new[] { Manifest.Permission.ReadExternalStorage }, 1);
}
#endif
}
var fileSaverResult = await FileSaver.Default.SaveAsync(attachment.AttachmentName, stream, cancellationToken);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论