【问题标题】:Xamarin Android - FilePickerActivity - Cancels For No ReasonXamarin Android - FilePickerActivity - 无缘无故取消
【发布时间】:2017-08-02 01:52:12
【问题描述】:

我有一些用于在 Android 上选择文件的代码。我是从网上某处挑选的。实际上,代码在一种情况下工作,但在我的应用程序中,它不起作用。 Android 认为用户实际上没有取消文件选择。

代码如下:

private Task<FileData> PickAndOpenFile(bool isSave)
{
    var id = GetRequestId();

    var ntcs = new TaskCompletionSource<FileData>(id);

    if (Interlocked.CompareExchange(ref _CompletionSource, ntcs, null) != null)
    {
        throw new InvalidOperationException("Only one operation can be active at a time");
    }

    try
    {
        var pickerIntent = new Intent(_Context, typeof(FilePickerActivity));
        pickerIntent.SetFlags(ActivityFlags.NewTask);

        _Context.StartActivity(pickerIntent);

        EventHandler<FilePickerEventArgs> handler = null;
        EventHandler<EventArgs> cancelledHandler = null;

        handler = (s, e) =>
        {
            var tcs = Interlocked.Exchange(ref _CompletionSource, null);

            FilePickerActivity.FilePicked -= handler;

            Stream fileStream = isSave ? File.OpenRead(e.FilePath) : File.OpenWrite(e.FilePath);

            tcs?.SetResult(new FileData { FileName = e.FileName, FileStream = fileStream });
        };

        cancelledHandler = (s, e) =>
        {
            var tcs = Interlocked.Exchange(ref _CompletionSource, null);

            FilePickerActivity.FilePickCancelled -= cancelledHandler;

            tcs?.SetResult(null);
        };

        FilePickerActivity.FilePickCancelled += cancelledHandler;
        FilePickerActivity.FilePicked += handler;
    }
    catch (Exception exAct)
    {
        Debug.Write(exAct);
    }

    return _CompletionSource.Task;
}

要看到它正确运行,请克隆这个 repo 并运行 android 示例。选择文件示例位于第二个选项卡上。 https://github.com/MelbourneDeveloper/Adapt.Presentation.git

但是,在我的应用程序中,我使用的代码完全相同:

            var filePicker = App.PlatformSpecificStartupArguments.PresentationFactory.CreateFilePicker();
            using (var fileData = await filePicker.PickAndOpenFileForReading())
            {
                if (fileData == null)
                {
                    return;
                }

                using (var readFileStream = fileData.FileStream)
                {
                    var fileExtension = Path.GetExtension(fileData.FileName);
                    var relativeUri = Guid.NewGuid() + fileExtension;
                    await OnPictureTakenAsync(this, new PictureTakenEventArgs(readFileStream, relativeUri, fileData.FileName));
                }
            }

但是,当我选择文件(从现有图像中选择图像)时,代码会进入 cancelledHandler。这显然是权限问题,因为我在设备日志中收到此错误消息:

08-02 15:15:28.697 LGE Nexus 5X 错误 18911 DatabaseUtils java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/images/来自 pid=18684、uid=10221 的媒体需要 android.permission.READ_EXTERNAL_STORAGE 或 grantUriPermission() 在 android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:608) 在 android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:483) 在 android.content.ContentProvider$Transport.query(ContentProvider.java:212) 在 android.content.ContentProviderNative.onTransact(ContentProviderNative.java:112) 在 android.os.Binder.execTransact(Binder.java:565)

因此,我在 Visual Studio 级别的 Android Manifest 中打开了此权限,但问题仍然存在。我针对失败的 Android 版本是 6.0。您可以看到,在上面提到的 repo 中,目标版本设置为“使用 SDK 版本进行编译”。而且我什至没有将 READ_EXTERNAL_STORAGE 添加到该示例应用程序中。

【问题讨论】:

    标签: c# android xamarin xamarin.android filepicker


    【解决方案1】:

    我在 Visual Studio 级别的 Android Manifest 中打开了此权限,但问题仍然存在。

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

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

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

    java.lang.SecurityException: Permission Denial: 读取 com.android.providers.media.MediaProvider ... 需要 android.permission.READ_EXTERNAL_STORAGE

    READ_EXTERNAL_STORAGE 被划分为Dangerous permissions,因此您应该手动检查 API 级别 23 及以上的权限。

    Here 是一个关于如何在运行时请求权限的示例。

    【讨论】:

    • 谢谢。您的帖子使我得到了最终答案。为此,我一直在使用 James Montemontagno 的代码,但该代码尚未准备好要求的权限,因此我编辑了该代码以解决问题。我将写另一篇文章并列出完整的解决方案。
    猜你喜欢
    • 2017-04-11
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2018-06-14
    • 2021-02-09
    • 1970-01-01
    • 2021-12-26
    相关资源
    最近更新 更多