Xamarin Android - 从图库中选择图像并获取其路径

时间:2015-04-20 05:41:16

标签: c# android mono xamarin xamarin.android

我一直在尝试在线找到多种解决方案,但尚未找到一种有效的解决方案。

我正在尝试从图库中选择图片,然后上传它。现在,我只想弄清楚如何获得图像的路径。

我首先尝试了找到here的配方,然而,总是返回null作为答案。

我现在正试图使用​​这个代码,我从另一个SO问题中找到了这个代码。

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

但是,路径仍为空。

如何获取所选图像的路径?

2 个答案:

答案 0 :(得分:1)

从以下位置更改imagePath:

imagePath = GetPathToImage(uri);

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

然后将以下类添加到您的项目中:

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);
        }
    }
}

这个类应该能够处理你抛出的任何Uri并返回FilePath。不要忘记将命名空间导入您的Activity!希望有所帮助。改编自here

答案 1 :(得分:-1)

像这样实现此方法'GetPathToImage',以提取设备上图像的路径并显示。

使用以下内容将辅助方法GetPathToImage添加到您的Activity:

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;

}

希望这会对你有所帮助。