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

Posted

技术标签:

【中文标题】Xamarin Android - 从图库中选择图像并获取其路径【英文标题】:Xamarin Android - Choose image from gallery and get its path 【发布时间】:2015-04-20 05:41:16 【问题描述】:

我一直在尝试在网上找到的多种解决方案,但还没有找到一种有效的解决方案。

我正在尝试从图库中选择一张图片,然后上传。目前,我只是想弄清楚如何获取图像的路径。

我首先尝试了找到 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;
    

但是,路径仍然为空。

如何获取选中图片的路径?

【问题讨论】:

【参考方案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。不要忘记将命名空间导入到您的活动中!希望有帮助。改编自here

【讨论】:

【参考方案2】:

像这样实现这个方法'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;

希望这会对您有所帮助。

【讨论】:

这就是我链接的食谱所说的。这也返回 null。

以上是关于Xamarin Android - 从图库中选择图像并获取其路径的主要内容,如果未能解决你的问题,请参考以下文章

如何从图库中选择图像并保存到 xamarin 中的 sql 数据库

Android:如何在设置图像视图时检测从图库中选择的图像方向(纵向或横向)?

Xamarin - 是不是有与适用于 Android 的 Photokit (iOS) 类似的框架,或者是获取图库中所有图像的文件流的好方法?

Xamarin - 将图像下载到图库

android从图库中选择图像

如果从图库中选择图像或选择视频,则在 onActivityResult 中识别 - Android