在Android设备上从图库中选择图片时出现权限问题

时间:2018-11-26 22:22:00

标签: android xamarin permissions

我从Xamarin开始,以便能够创建同时在iOS和Android上运行的应用程序。 我要做的第一件事是单击一个按钮->打开图库->选择图像->在图像标签上显示所选图像

MainPage.xaml的当前内容为:

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:HelloWorld" x:Class="HelloWorld.MainPage">
    <StackLayout>
        <!-- Place new controls here -->
        <Label Text="Welcome to Xamarin.Forms!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
        <Label Text="0" x:Name="lbl_counter" HorizontalOptions="Center" VerticalOptions="StartAndExpand" FontSize="Large"/> 
        <Image x:Name="img_selected" Source="" /> 
        <Button Text="Click Me" Clicked="Handle_Clicked" VerticalOptions="StartAndExpand"/>
    </StackLayout>
</ContentPage>

我正在使用Plugin.Media,因此,当单击按钮时,我运行以下代码:

async void Handle_Clicked(object sender, System.EventArgs e){
    lbl_counter.Text = (++counter).ToString();

    await CrossMedia.Current.Initialize();
    if (!CrossMedia.Current.IsPickPhotoSupported){
        await DisplayAlert("no upload", "picking a photo is not supported", "ok");
        return;
    }

    var file = await CrossMedia.Current.PickPhotoAsync();
    if (file == null)
        return;

    img_selected.Source = ImageSource.FromStream(file.GetStream);
}

经过大量的努力,我设法使其在iOS上运行。 但是我无法在Android上使用它。它不断抱怨权限。 我已经从以下所有方面想到了我的想法:

有什么主意吗?


从评论中添加信息

评论1:

我在Xamarin中没有(可见的)堆栈跟踪。 如果我从错误窗口中复制,则会得到此信息:

Plugin.Media.Abstractions.MediaPermissionException: Storage permission(s) are required.

在“输出”窗口中,我可以看到:

Does not have storage permission granted, requesting.
Storage permission Denied.

代码

MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Plugin.Media;
using Plugin.Permissions;
using Plugin.Permissions.Abstractions;

namespace HelloWorld
{
    public partial class MainPage : ContentPage
    {
        private int counter;
        public MainPage()
        {
            InitializeComponent();
        }

        async void Handle_Clicked(object sender, System.EventArgs e)
        {
            lbl_counter.Text = (++counter).ToString();

            /******************************/
            try
            {
                var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
                if (status != PermissionStatus.Granted)
                {
                    if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Storage))
                    {
                        await DisplayAlert("Need Storage", "Gunna need that Storage", "OK");
                    }

                    var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Storage);
                    status = results[Permission.Storage];
                }

                if (status == PermissionStatus.Granted)
                {
                    await CrossMedia.Current.Initialize();
                    if (!CrossMedia.Current.IsPickPhotoSupported)
                    {
                        await DisplayAlert("no upload", "picking a photo is not supported", "ok");
                        return;
                    }

                    var file = await CrossMedia.Current.PickPhotoAsync();
                    if (file == null)
                        return;

                    img_selected.Source = ImageSource.FromStream(file.GetStream);
                }
                    else if (status != PermissionStatus.Unknown)
                {
                    await DisplayAlert("Storage Permission Denied", "Can not continue, try again.", "OK");
                }
            }
            catch
            {
                //...
            }
            /******************************/

        }
    }
}

MainPage.xaml

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:HelloWorld" x:Class="HelloWorld.MainPage">
    <StackLayout>
        <!-- Place new controls here -->
        <Label Text="Welcome to Xamarin.Forms!" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
        <Label Text="0" x:Name="lbl_counter" HorizontalOptions="Center" VerticalOptions="StartAndExpand" FontSize="Large"/> 
        <Image x:Name="img_selected" Source="" /> 
        <Button Text="Click Me" Clicked="Handle_Clicked" VerticalOptions="StartAndExpand"/>
    </StackLayout>
</ContentPage>

MainActivity.cs

using System;

using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace HelloWorld.Droid
{
    [Activity(Label = "HelloWorld", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
        {
            Plugin.Permissions.PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }

        protected override void OnCreate(Bundle savedInstanceState)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate(savedInstanceState);
            global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
            LoadApplication(new App());
        }
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.gedons.HelloWorld">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
    <uses-permission android:name="android.permission.CAMERA" />
    <application android:label="HelloWorld.Android">
        <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true">
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
        </provider>
    </application>
</manifest> 

_file_path.xml _

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="my_images" path="Pictures" />
    <external-files-path name="my_movies" path="Movies" />
</paths>

2 个答案:

答案 0 :(得分:0)

  

在Android上从图库中选择图像时出现权限问题

从Android 6.0(API级别23)开始,用户在应用程序运行时(而不是在安装应用程序时)授予应用程序权限。您应该在运行时requesting permissions

系统权限分为正常和危险两类:

  • 普通权限不会直接危害用户的隐私。如果您的应用在清单中列出了正常权限,则系统会自动授予该权限。
  • 危险权限可以使该应用访问用户的机密数据。如果您的应用在清单中列出了正常权限,则系统会自动授予该权限。如果您列出了危险许可,则用户必须明确批准您的应用。

READ_EXTERNAL_STORAGE分为Dangerous permissions,因此您应该手动检查API级别23及更高版本的此权限。


对于Xamarin.Forms项目,您可以在运行时使用PermissionsPluginXamarin.Forms中请求此权限。

此处使用简单,请将此代码添加到您的MainActivity中:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
    PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

在需要时请求权限:

try
{
    var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
    if (status != PermissionStatus.Granted)
    {
        if(await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Storage))
        {
            await DisplayAlert("Need Storage", "Gunna need that Storage", "OK");
        }

        var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Storage);
        status = results[Permission.Storage];
     }

     if (status == PermissionStatus.Granted)
     {
         //Permission granted, do what you want do.
     }
     else if(status != PermissionStatus.Unknown)
     {
         await DisplayAlert("Storage Permission Denied", "Can not continue, try again.", "OK");
     }
}
catch (Exception ex)
{
    //...
}

答案 1 :(得分:0)

从Android M开始,您必须拥有其他应用程序,例如(画廊)存储许可,即图库需要将选择的图像保存到提供的URI路径中。

请按照以下步骤操作: https://thinkandroid.wordpress.com/2012/08/07/granting-content-provider-uri-permissions/