简体   繁体   中英

Xamarin Android - Choose image from gallery and get its path

I have been trying multiple solutions found online, and have yet to find one that works.

I am attempting to select an image from the gallery, then upload it. For now, I am just trying to figure out how to get the path to the image.

I first tried the recipe found here , however, that always returned null as the answer.

I am now attempting to use this code, which I found from another SO question.

    public static readonly int ImageId = 1000;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);


        GetImage(((b, p) => {
            Toast.MakeText(this, "Found path: " + p, ToastLength.Long).Show();
        }));
    }

    public delegate void OnImageResultHandler(bool success, string imagePath);

    protected OnImageResultHandler _imagePickerCallback;
    public void GetImage(OnImageResultHandler callback)
    {
        if (callback == null) {
            throw new ArgumentException ("OnImageResultHandler callback cannot be null.");
        }

        _imagePickerCallback = callback;
        InitializeMediaPicker();
    }

    public void InitializeMediaPicker()
    {
        Intent = new Intent();
        Intent.SetType("image/*");
        Intent.SetAction(Intent.ActionGetContent);
        StartActivityForResult(Intent.CreateChooser(Intent, "Select Picture"), 1000);
    }

    protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
    {
        if ((requestCode != 1000) || (resultCode != Result.Ok) || (data == null)) {
            return;
        }

        string imagePath = null;
        var uri = data.Data;
        try {
            imagePath = GetPathToImage(uri);
        } catch (Exception ex) {
            // Failed for some reason.
        }

        _imagePickerCallback (imagePath != null, imagePath);
    }

    private string GetPathToImage(Android.Net.Uri uri)
    {
        string doc_id = "";
        using (var c1 = ContentResolver.Query (uri, null, null, null, null)) {
            c1.MoveToFirst ();
            String document_id = c1.GetString (0);
            doc_id = document_id.Substring (document_id.LastIndexOf (":") + 1);
        }

        string path = null;

        // The projection contains the columns we want to return in our query.
        string selection = Android.Provider.MediaStore.Images.Media.InterfaceConsts.Id + " =? ";
        using (var cursor = ManagedQuery(Android.Provider.MediaStore.Images.Media.ExternalContentUri, null, selection, new string[] {doc_id}, null))
        {
            if (cursor == null) return path;
            var columnIndex = cursor.GetColumnIndexOrThrow(Android.Provider.MediaStore.Images.Media.InterfaceConsts.Data);
            cursor.MoveToFirst();
            path = cursor.GetString(columnIndex);
        }
        return path;
    }

However, the path is still null.

How can I get the path of the selected image?

Change imagePath from:

imagePath = GetPathToImage(uri);

To

imagePath = UriHelper.GetPathFromUri(this, data.Data);

And then add the following Class to your project:

using Android.Content;
using Android.Database;
using Android.OS;
using Android.Provider;
using DroidEnv = Android.OS.Environment;
using DroidUri = Android.Net.Uri;

namespace MyApp.Helpers
{
    public static class UriHelper
    {
        /// <summary>
        /// Method to return File path of a Gallery Image from URI.
        /// </summary>
        /// <param name="context">The Context.</param>
        /// <param name="uri">URI to Convert from.</param>
        /// <returns>The Full File Path.</returns>
        public static string GetPathFromUri(Context context, DroidUri uri)
        {

            //check here to KITKAT or new version
            // bool isKitKat = Build.VERSION.SdkInt >= Build.VERSION_CODES.Kitkat;
            bool isKitKat = Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat;

            // DocumentProvider
            if (isKitKat && DocumentsContract.IsDocumentUri(context, uri))
            {

                // ExternalStorageProvider
                if (isExternalStorageDocument(uri))
                {
                    string docId = DocumentsContract.GetDocumentId(uri);
                    string[] split = docId.Split(':');
                    string type = split[0];

                    if (type.Equals("primary", System.StringComparison.InvariantCultureIgnoreCase))
                    {
                        return DroidEnv.ExternalStorageDirectory + "/" + split[1];
                    }
                }
                // DownloadsProvider
                else if (isDownloadsDocument(uri))
                {

                    string id = DocumentsContract.GetDocumentId(uri);
                    DroidUri ContentUri = ContentUris.WithAppendedId(
                      DroidUri.Parse("content://downloads/public_downloads"), long.Parse(id));

                    return GetDataColumn(context, ContentUri, null, null);
                }
                // MediaProvider
                else if (isMediaDocument(uri))
                {
                    string docId = DocumentsContract.GetDocumentId(uri);
                    string[] split = docId.Split(':');
                    string type = split[0];

                    DroidUri 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] };

                    return GetDataColumn(context, contentUri, selection, selectionArgs);
                }
            }
            // MediaStore (and general)
            else if (uri.Scheme.Equals("content", System.StringComparison.InvariantCultureIgnoreCase))
            {

                // Return the remote address
                if (isGooglePhotosUri(uri))
                    return uri.LastPathSegment;

                return GetDataColumn(context, uri, null, null);
            }
            // File
            else if (uri.Scheme.Equals("file", System.StringComparison.InvariantCultureIgnoreCase))
            {
                return uri.Path;
            }

            return null;
        }

       /// <summary>
       /// Get the value of the data column for this URI. This is useful for
       /// MediaStore URIs, and other file-based ContentProviders.
       /// </summary>
       /// <param name="context">The Context.</param>
       /// <param name="uri">URI to Query</param>
       /// <param name="selection">(Optional) Filter used in the Query.</param>
       /// <param name="selectionArgs">(Optional) Selection Arguments used in the Query.</param>
       /// <returns>The value of the _data column, which is typically a File Path.</returns>
        private static string GetDataColumn(Context context, DroidUri 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;
        }

        /// <param name="uri">The URI to Check.</param>
        /// <returns>Whether the URI Authority is ExternalStorageProvider.</returns>
        private static bool isExternalStorageDocument(DroidUri uri)
        {
            return "com.android.externalstorage.documents".Equals(uri.Authority);
        }


         /// <param name="uri">The URI to Check.</param>
         /// <returns>Whether the URI Authority is DownloadsProvider.</returns>
        private static bool isDownloadsDocument(DroidUri uri)
        {
            return "com.android.providers.downloads.documents".Equals(uri.Authority);
        }


         /// <param name="uri">The URI to Check.</param>
         /// <returns>Whether the URI Authority is MediaProvider.</returns>
        private static bool isMediaDocument(DroidUri uri)
        {
            return "com.android.providers.media.documents".Equals(uri.Authority);
        }


         /// <param name="uri">The URI to check.</param>
         /// <returns>Whether the URI Authority is Google Photos.</returns>
        private static bool isGooglePhotosUri(DroidUri uri)
        {
            return "com.google.android.apps.photos.content".Equals(uri.Authority);
        }
    }
}

This class should be able to handle any Uri you throw at it and return the FilePath. Don't forget to import the namespace into your Activity! Hope that helps. Adapted from here

Implement this method 'GetPathToImage' like this to extract the path to the image on the device and display.

Add the helper method GetPathToImage to your Activity with the following contents:

private string GetPathToImage(Uri uri)
 {
   string path = null;
   // The projection contains the columns we want to return in our query.
   string[] projection = new[]       {Android.Provider.MediaStore.Images.Media.InterfaceConsts.Data };
     using (ICursor cursor = ManagedQuery(uri, projection, null, null,  null))
     {
       if (cursor != null)
       {
         int columnIndex =   cursor.GetColumnIndexOrThrow(Android.Provider.MediaStore.Images.Media.InterfaceConsts.Data);
        cursor.MoveToFirst();
        path = cursor.GetString(columnIndex);
       }
     }

return path;

}

Hope this will help you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM