提问人:Marcel Delhaye 提问时间:11/10/2023 最后编辑:Marcel Delhaye 更新时间:11/17/2023 访问量:86
Android 13:Xamarin.Forms 不授予访问库图像的权限
Android 13: Xamarin.Forms doesn't give permissions to access gallery images
问:
自 Android 13 以来,我的 Xamarin.Forms 应用不再具有访问库中图像所需的权限。我知道 Google 已经更改了访问条件,我们需要用细粒度媒体权限替换READ_EXTERNAL_STORAGE:READ_MEDIA_IMAGES、READ_MEDIA_VIDEO和READ_MEDIA_AUDIO。 我已经应用了所有这些更改,但对图像的访问仍然被拒绝(我没有来自系统的权限请求)。更糟糕的是,当我自己手动分配权限时,它也不起作用。最后,Xamarin.Essentials 组件(我使用的是 1.8.0 版)似乎没有考虑 Android 13 施加的更改。有更新计划吗?有没有办法解决这个问题? 这是我的AndroidManifest.xml文件:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.ApriSoft.memocourses" android:installLocation="auto" android:versionName="5.0.3" android:versionCode="503">
<uses-sdk android:minSdkVersion="20" android:targetSdkVersion="33" />
<application android:label="MemoCourses.Android">
<activity android:name="microsoft.identity.client.BrowserTabActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="msauth" android:host="com.ApriSoft.memocourses" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
和 MainActivity.cs 文件:
using System;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms;
using static MemoCourses.Droid.MainActivity;
using Android.Content;
using Microsoft.Identity.Client;
using Xamarin.Essentials;
using MemoCourses.Models;
using System.Collections.ObjectModel;
using Android.Text.Method;
using Android.Text;
using Plugin.CurrentActivity;
[assembly: ExportRenderer(typeof(Entry), typeof(MyEntryRenderer))]
[assembly: UsesPermission(Android.Manifest.Permission.Camera)]
[assembly: UsesPermission(Android.Manifest.Permission.ReadMediaImages)]/* CSS Document*/
namespace MemoCourses.Droid
{
[Activity(Label = "MemoCourses", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, ScreenOrientation = ScreenOrientation.Portrait)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Rg.Plugins.Popup.Popup.Init(this);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
App.AuthUIParent = this;
Window.SetStatusBarColor(Android.Graphics.Color.Argb(255, 47, 56, 40));
ButtonCircleRenderer.Init();
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
global::ZXing.Net.Mobile.Android.PermissionsHandler.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
}
public override void OnBackPressed()
{
Rg.Plugins.Popup.Popup.SendBackPressed(base.OnBackPressed);
}
}
}
这是我用来选择图像的代码:
try
{
FileData fileData = await CrossFilePicker.Current.PickFile();
//
var filepath = fileData.FilePath;
//
if (fileData == null)
return; // user canceled file picking
newimageByte = fileData.DataArray;
resizedImageByte = await ImageResizer.ResizeImage(newimageByte, 200, 200);
if (resizedImageByte != null)
{
var stream1 = new MemoryStream(resizedImageByte);
ImageArticle.Source = ImageSource.FromStream(() => stream1);
}
}
catch (Exception ex)
{
imageGallery = false;
imageChanged = false;
}
非常感谢你对我的帮助,我已经找了好几天了,找不到解决方案。我的应用的所有用户(其手机已更新到 Android 13)都无法再从图库中选择图像。
答:
0赞
Guangyu Bai - MSFT
11/13/2023
#1
我在我这边测试了该方法,效果很好。您可以使用以下代码在 Android 13 上上传图片。请把代码放在班级里。MainActivity
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
if (Xamarin.Essentials.DeviceInfo.Version.Major >= 13 && (permissions.Where(p => p.Equals("android.permission.WRITE_EXTERNAL_STORAGE")).Any() || permissions.Where(p => p.Equals("android.permission.READ_EXTERNAL_STORAGE")).Any()))
{
var wIdx = Array.IndexOf(permissions, "android.permission.WRITE_EXTERNAL_STORAGE");
var rIdx = Array.IndexOf(permissions, "android.permission.READ_EXTERNAL_STORAGE");
if (wIdx != -1 && wIdx < permissions.Length) grantResults[wIdx] = Permission.Granted;
if (rIdx != -1 && rIdx < permissions.Length) grantResults[rIdx] = Permission.Granted;
}
Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
我制作了一个演示,你可以尝试使用它通过 Xamarin.Essentials: Media Picker 从照片中获取图像。
下面是 Mainpage.xaml 中的代码。
<Image x:Name="FotoProduto"></Image>
<Button x:Name="button" Text="button" Clicked="button_Clicked"></Button>
Mainpage.xaml.cs 中的代码。
private async void button_Clicked(object sender, EventArgs e)
{
var result = await MediaPicker.PickPhotoAsync(new MediaPickerOptions
{
Title = "Choise the product photo"
});
var stream = await result.OpenReadAsync();
FotoProduto.Source = ImageSource.FromStream(() => stream);
}
Mainpage.xaml.cs 中的更新方法
不要使用流方式。
var result = await MediaPicker.PickPhotoAsync(new MediaPickerOptions
{
Title = "Choise the product photo"
});
var newFile = Path.Combine(FileSystem.CacheDirectory, result.FileName);
FotoProduto.Source = newFile;
评论
0赞
Marcel Delhaye
11/14/2023
感谢您的回答,但不幸的是,我将您给我的代码添加到了 MainActivity.cs 文件中,但它不起作用。我在问题中添加了用于选择图像的代码部分。这是拒绝访问的地方。也许是 CrossFilePicker 命令导致了问题?
0赞
Guangyu Bai - MSFT
11/15/2023
CrossFilePicker
不再受支持。可以使用 Xamarin.Essentials: Media Picker 选取照片或库中的图像。
0赞
Guangyu Bai - MSFT
11/15/2023
我编辑了我的答案以提供代码,您可以使用它来获取照片。
0赞
Marcel Delhaye
11/16/2023
再次感谢,但现在我有另一个问题:在这行代码上,流是正确的(CanRead = true CanWrite = false Length = 2237991),但下一行给了我错误。还有.为什么?谢谢你的帮助。var stream = await result.OpenReadAsync();
Length = System.ObjectDisposedException: Cannot access a disposed object
Object name: 'Stream has been closed'. System.ArgumentNullException: 'Buffer cannot be null. Parameter name: buffer'
0赞
Guangyu Bai - MSFT
11/17/2023
您可以使用这些代码,而不是使用流。var result = await MediaPicker.PickPhotoAsync(new MediaPickerOptions { Title = "Choise the product photo" }); var newFile = Path.Combine(FileSystem.CacheDirectory, result.FileName); FotoProduto.Source = newFile;
评论
app no longer has the required permissions to access the images in the gallery.
不知道你认为什么 “画廊”在Android设备上。但是使用普通的 Android 图像或文件选择器,永远不需要任何权限即可这样做。也不用于访问使用获得的 uri 的文件。can no longer upload an image
上传?这是第三步。首先是采摘和打开。