如何从Uri xamarin android获取实际路径

我想从Uri获取实际路径,当我使用intent选择文件时,它将返回URI但是下面的代码行不能用于转换URI到字符串路径

打开FilePicker

public static void PickFile(Activity context) { Intent intent = new Intent(Intent.ActionGetContent); intent.SetType("*/*"); context.StartActivityForResult(intent, PICKFILE_RESULT_CODE); } 

获得结果

 protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { if(requestCode == PICKFILE_RESULT_CODE) { string filepath = GetRealPathFromURI(MainActivity.act, data.Data); } } public static string GetRealPathFromURI(Activity act, Android.Net.Uri contentURI) { try { ICursor cursor = act.ContentResolver.Query(contentURI, null, null, null, null); cursor.MoveToFirst(); string documentId = cursor.GetString(0); documentId = documentId.Split(':')[1]; cursor.Close(); cursor = act.ContentResolver.Query( MediaStore.Images.Media.ExternalContentUri, null, MediaStore.Images.Media.InterfaceConsts.Id + " = ? ", new[] { documentId }, null); cursor.MoveToFirst(); string path = cursor.GetString(cursor.GetColumnIndex(MediaStore.Images.Media.InterfaceConsts.Data)); cursor.Close(); return path; } catch(Exception e) { Log.Debug("TAG_DATA",e.ToString()); return ""; } } 

错误

System.IndexOutOfRangeException:索引超出了数组的范围。

任何人都可以向我解释,我在这段代码中做错了什么。

如何从Uri xamarin android获取实际路径

我注意到你正在使用MediaStore.Images.Media.ExternalContentUri属性,你想要的是获得Gallery Image的真实路径?

如果你想实现这个function,你可以阅读我的答案: 获取图库图像的路径?

 private string GetRealPathFromURI(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 = ContentResolver.Query(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; } 

更新:

这是一个解决方案:

 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)) { return Android.OS.Environment.ExternalStorageDirectory + "/" + split[1]; } } // 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()); return getDataColumn(this, contentUri, null, null); } // 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] }; return getDataColumn(this, contentUri, selection, selectionArgs); } } // MediaStore (and general) else if ("content".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase)) { // Return the remote address if (isGooglePhotosUri(uri)) return uri.LastPathSegment; return getDataColumn(this, uri, null, null); } // File else if ("file".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase)) { return uri.Path; } return null; } 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); } 

获取OnActivityResult的实际路径:

 protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); if (requestCode == 0) { var uri = data.Data; string path = GetActualPathFromFile(uri); System.Diagnostics.Debug.WriteLine("Image path == " + path); } } 

阅读这篇文章,您将得到完全简单的答案。

https://commonsware.com/blog/2016/03/15/how-consume-content-uri.html

我的代码如下:

  var targetPath = $"{FileDir}{Path.DirectorySeparatorChar}{FileName}"; const int bufferSize = 1024; using (var inputStream = Activity.ContentResolver.OpenInputStream(audioFileUri)) { using (var outputStream = File.Create(targetPath)) { var buffer = new byte[bufferSize]; while (true) { var count = inputStream.Read(buffer, 0, bufferSize); if (count > 0) { outputStream.Write(buffer, 0, count); } if (count < bufferSize) break; } } }