Action.Picker возвращает неверный / неправильный Uri (Как получить путь или байт [] из нескольких выбранных галерей img) - PullRequest
0 голосов
/ 11 сентября 2018

У меня есть приложение для форм, где мне нужно выбрать изображения «1 ко многим» из памяти телефона. Для этого я использую систему внедрения зависимостей.

Моя проблема в том, где я получаю Android.netUri, который разрешается в файл, который не существует ... и в имя файла, которое я никогда раньше не видел. Кикер в том, что если я выбираю снимки, которые были сделаны в течение последних нескольких часов, этот код работает ...

Я нахожусь в конце своего прыжка, я действительно надеюсь, что кто-то может указать мне на то, что я делаю неправильно.

Я запускаю операцию выбора с:

[assembly: Dependency(typeof(ImagePickerService))]
namespace MyApp.Droid
{
    public class ImagePickerService : Java.Lang.Object, IImagePickerService
    {
        public async Task OpenGallery()
        {
            try
            {
                var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
                if (status != PermissionStatus.Granted)
                {
                    if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Storage))
                    {
                        Toast.MakeText(CrossCurrentActivity.Current.Activity, "Need Storage permission to access to your photos.", ToastLength.Long).Show();
                    }

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

                if (status == PermissionStatus.Granted)
                {
                    Toast.MakeText(CrossCurrentActivity.Current.Activity, "Pick max 20 images", ToastLength.Long).Show();
                    var imageIntent = new Intent(Intent.ActionPick);
                    imageIntent.SetType("image/*");
                    imageIntent.PutExtra(Intent.ExtraAllowMultiple, true);
                    imageIntent.SetAction(Intent.ActionPick);
                    CrossCurrentActivity.Current.Activity.StartActivityForResult(Intent.CreateChooser(imageIntent, "Pick pictures"), 100);

                }
                else if (status != PermissionStatus.Unknown)
                {
                    Toast.MakeText(CrossCurrentActivity.Current.Activity, "Permission Denied. Can not continue, try again.", ToastLength.Long).Show();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                Toast.MakeText(CrossCurrentActivity.Current.Activity, "Error. Can not continue, try again.", ToastLength.Long).Show();
            }
        }

    }

тогда в моем MainActivity.cs у меня есть OnActivityResult Я попытался использовать ContentResolver.OpenInputStream для получения байтов изображения без удачи, так что это закомментировано atm.

        protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            base.OnActivityResult(requestCode, resultCode, data);

            if (requestCode == OPENGALLERYCODE && resultCode == Result.Ok)
            {
                List<string> images = new List<string>();

                if (data != null)
                {
                    ClipData clipData = data.ClipData;
                    if (clipData != null)
                    {
                        for (int i = 0; i < clipData.ItemCount; i++)
                        {
                            ClipData.Item item = clipData.GetItemAt(i);
                            /*
                            var stream = ContentResolver.OpenInputStream(item.Uri); //This throws "FileNotFound"
                            byte[] byteArray;
                            using (var memoryStream = new MemoryStream())
                            {
                                stream.CopyTo(memoryStream);
                                byteArray = memoryStream.ToArray();
                                stream.Close();
                                stream = null;
                            }
                            stream = ContentResolver.OpenInputStream(item.Uri);
                            var exif = new ExifInterface(stream);
                            stream.Close();
                            */

                            Android.Net.Uri uri = item.Uri;
                            var path = GetActualPathFromFile(uri);

                            if (path != null)
                            {
                                var tmpImgPath = RotateToOriginalDimention(path);
                                images.Add(tmpImgPath);
                            }
                        }
                    }
                    else
                    {
                        Android.Net.Uri uri = data.Data;
                        var path = GetActualPathFromFile(uri);

                        if (path != null)
                        {
                            var tmpImgPath = RotateToOriginalDimention(path);
                            images.Add(tmpImgPath);
                        }
                    }
                    MessagingCenter.Send<App, List<string>>((App)Xamarin.Forms.Application.Current, "ImagesSelected", images);
                }
            }
        }

И GetActualPathFromFile (также в моем MainActivity.cs) Дырочная функция ниже, но я нажимаю эту часть кода и получаю «FileNotFound»

(...)
                else if ("content".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
                {

                    var retval2 = getDataColumn(this, uri, null, null);
                    if (File.Exists(retval2)) //<----------------------- This returns "false"
                    {
                        return retval2;
                    }
                    else
                    {
                        throw new Exception("file not found " + retval2);
                    }
                }
(...)

Отверстие GetActualPathFromFile

        private string GetActualPathFromFile(Android.Net.Uri uri)
        {
            bool isKitKat = Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat;

            if (isKitKat && DocumentsContract.IsDocumentUri(this, uri))
            {
                // ExternalStorageProvider
                if (isExternalStorageDocument(uri))
                {
                    string docId = DocumentsContract.GetDocumentId(uri);

                    char[] chars = { ':' };
                    string[] split = docId.Split(chars);
                    string type = split[0];

                    if ("primary".Equals(type, StringComparison.OrdinalIgnoreCase))
                    {
                        var retval = Android.OS.Environment.ExternalStorageDirectory + "/" + split[1];
                        if (File.Exists(retval))
                        {
                            return retval;
                        }
                        else
                        {
                            throw new Exception("file not found " + retval);
                        }
                    }
                }
                // DownloadsProvider
                else if (isDownloadsDocument(uri))
                {
                    string id = DocumentsContract.GetDocumentId(uri);

                    Android.Net.Uri contentUri = ContentUris.WithAppendedId(
                                    Android.Net.Uri.Parse("content://downloads/public_downloads"), long.Parse(id));

                    //System.Diagnostics.Debug.WriteLine(contentUri.ToString());

                    var retval = getDataColumn(this, contentUri, null, null);
                    if (File.Exists(retval))
                    {
                        return retval;
                    }
                    else
                    {
                        throw new Exception("file not found " + retval);
                    }
                }
                // MediaProvider
                else if (isMediaDocument(uri))
                {
                    String docId = DocumentsContract.GetDocumentId(uri);

                    char[] chars = { ':' };
                    String[] split = docId.Split(chars);

                    String type = split[0];

                    Android.Net.Uri contentUri = null;
                    if ("image".Equals(type))
                    {
                        contentUri = MediaStore.Images.Media.ExternalContentUri;
                    }
                    else if ("video".Equals(type))
                    {
                        contentUri = MediaStore.Video.Media.ExternalContentUri;
                    }
                    else if ("audio".Equals(type))
                    {
                        contentUri = MediaStore.Audio.Media.ExternalContentUri;
                    }

                    String selection = "_id=?";
                    String[] selectionArgs = new String[]
                    {
                        split[1]
                    };

                    var retval = getDataColumn(this, contentUri, selection, selectionArgs);
                    if (File.Exists(retval))
                    {
                        return retval;
                    }
                    else
                    {
                        throw new Exception("file not found " + retval);
                    }
                }
            }
            // MediaStore (and general)
            else if ("content".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
            {

                // Return the remote address
                if (isGooglePhotosUri(uri))
                {
                    var retval = uri.LastPathSegment;
                    if (File.Exists(retval))
                    {
                        return retval;
                    }
                    else
                    {
                        throw new Exception("file not found " + retval);
                    }
                }


                var retval2 = getDataColumn(this, uri, null, null);
                if (File.Exists(retval2))
                {
                    return retval2;
                }
                else
                {
                    throw new Exception("file not found " + retval2);
                }
            }
            // File
            else if ("file".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
            {
                var retval = uri.Path;
                if (File.Exists(retval))
                {
                    return retval;
                }
                else
                {
                    throw new Exception("file not found " + retval);
                }
            }

            throw new Exception("file not found ");
        }

        public static String getDataColumn(Context context, Android.Net.Uri uri, String selection, String[] selectionArgs)
        {
            ICursor cursor = null;
            String column = "_data";
            String[] projection =
            {
                column
            };

            try
            {
                cursor = context.ContentResolver.Query(uri, projection, selection, selectionArgs, null);
                if (cursor != null && cursor.MoveToFirst())
                {
                    int index = cursor.GetColumnIndexOrThrow(column);
                    return cursor.GetString(index);
                }
            }
            finally
            {
                if (cursor != null)
                    cursor.Close();
            }
            return null;
        }

        //Whether the Uri authority is ExternalStorageProvider.
        public static bool isExternalStorageDocument(Android.Net.Uri uri)
        {
            return "com.android.externalstorage.documents".Equals(uri.Authority);
        }

        //Whether the Uri authority is DownloadsProvider.
        public static bool isDownloadsDocument(Android.Net.Uri uri)
        {
            return "com.android.providers.downloads.documents".Equals(uri.Authority);
        }

        //Whether the Uri authority is MediaProvider.
        public static bool isMediaDocument(Android.Net.Uri uri)
        {
            return "com.android.providers.media.documents".Equals(uri.Authority);
        }

        //Whether the Uri authority is Google Photos.
        public static bool isGooglePhotosUri(Android.Net.Uri uri)
        {
            return "com.google.android.apps.photos.content".Equals(uri.Authority);
        }

1 Ответ

0 голосов
/ 12 сентября 2018

Обнаружено, что реальная проблема заключается в том, что приложение Google Photos не обновлялось и по-прежнему показывало изображения, которые были удалены.

После двухкратной перезагрузки телефона приложение Google Фото наконец обновилось. Так что это больше похоже на проблему с кешем в Google Foto, чем на xamarin.

...