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) 类似的框架,或者是获取图库中所有图像的文件流的好方法?