2016-11-02 7 views
2

у меня есть кнопка, чтобы прикрепить файлXamarin: GetRealPathFromURI работает для изображений, но не для других файлов

private void ImgAttach_Click(object sender, EventArgs e) 
     { 
      var _Intent = new Intent(); 
      _Intent.SetType("*/*"); 
      _Intent.SetAction(Intent.ActionGetContent); 
      StartActivityForResult(Intent.CreateChooser(_Intent, "Select File"), 0); 
     } 

После выбора файла, я могу получить реальный путь, если это изображение. Если это не изображение (PDF, DOCX), оно не работает! Например, вот путь возвращается после выбора изображения:

"/storage/0403-0201/Pictures/beach_huts.jpg" 

, но после выбора файла, эта ошибка появляется

Android.Database.CursorIndexOutOfBoundsException: Индекс 0 просил, с размером 0

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) 
{ 
      base.OnActivityResult(requestCode, resultCode, data); 

      if (resultCode == Result.Ok) 
      { 
       Android.Net.Uri selectedUri = data.Data; 
       //////////////////////// 
       string s = GetRealPathFromURI(selectedUri); 
      } 
} 

private string GetRealPathFromURI(Android.Net.Uri contentURI) 
     { 
      Android.Database.ICursor cursor = ContentResolver.Query(contentURI, null, null, null, null); 
      cursor.MoveToFirst(); 
      string documentId = cursor.GetString(0); 
      documentId = documentId.Split(':')[1]; 
      cursor.Close(); 

      cursor = ContentResolver.Query(
      Android.Provider.MediaStore.Images.Media.ExternalContentUri, 
      null, Android.Provider.MediaStore.Images.Media.InterfaceConsts.Id + " = ? ", new[] { documentId }, null); 
      cursor.MoveToFirst(); 
      string path = cursor.GetString(cursor.GetColumnIndex(Android.Provider.MediaStore.Images.ImageColumns.Data)); 
      cursor.Close(); 

      return path; 
     } 

ответ

2

Это ответ

/** 
* Get a file path from a Uri. This will get the the path for Storage Access 
* Framework Documents, as well as the _data field for the MediaStore and 
* other file-based ContentProviders. 
* 
* @param context The context. 
* @param uri The Uri to query. 
* @author paulburke 
*/ 
     public static string GetRealPathFromURI(Context context,Android.Net.Uri uri) 
     { 

      bool isKitKat = Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat; 

      // DocumentProvider 
      if (isKitKat && Android.Provider.DocumentsContract.IsDocumentUri(context, uri)) 
      { 
       // ExternalStorageProvider 
       if (isExternalStorageDocument(uri)) 
       { 
        string docId = Android.Provider.DocumentsContract.GetDocumentId(uri); 
        string[] split = docId.Split(':'); 
        string type = split[0]; 

        if ("primary".Equals(type,StringComparison.OrdinalIgnoreCase)) 
        { 
         return Android.OS.Environment.ExternalStorageDirectory + "/" + split[1]; 
        } 

        // TODO handle non-primary volumes 
       } 
       // DownloadsProvider 
       else if (isDownloadsDocument(uri)) 
       { 

        string id = Android.Provider.DocumentsContract.GetDocumentId(uri); 
        Android.Net.Uri contentUri = ContentUris.WithAppendedId(Android.Net.Uri.Parse("content://downloads/public_downloads"), Convert.ToInt64(id)); 

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

        Android.Net.Uri contentUri = null; 
        if ("image".Equals(type)) 
        { 
         contentUri = Android.Provider.MediaStore.Images.Media.ExternalContentUri; 
        } 
        else if ("video".Equals(type)) 
        { 
         contentUri = Android.Provider.MediaStore.Video.Media.ExternalContentUri; 
        } 
        else if ("audio".Equals(type)) 
        { 
         contentUri = Android.Provider.MediaStore.Audio.Media.ExternalContentUri; 
        } 

        string selection = "_id=?"; 
        string[] selectionArgs = new string[] { 
        split[1] 
      }; 

        return getDataColumn(context, contentUri, selection, selectionArgs); 
       } 
      } 
      // MediaStore (and general) 
      else if ("content".Equals(uri.Scheme,StringComparison.OrdinalIgnoreCase)) 
      { 
       return getDataColumn(context, uri, null, null); 
      } 
      // File 
      else if ("file".Equals(uri.Scheme,StringComparison.OrdinalIgnoreCase)) 
      { 
       return uri.Path; 
      } 

      return null; 
     } 

     /** 
     * Get the value of the data column for this Uri. This is useful for 
     * MediaStore Uris, and other file-based ContentProviders. 
     * 
     * @param context The context. 
     * @param uri The Uri to query. 
     * @param selection (Optional) Filter used in the query. 
     * @param selectionArgs (Optional) Selection arguments used in the query. 
     * @return The value of the _data column, which is typically a file path. 
     */ 
     public static String getDataColumn(Context context,Android.Net.Uri uri, String selection, 
       String[] selectionArgs) 
     { 

      Android.Database.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 column_index = cursor.GetColumnIndexOrThrow(column); 
        return cursor.GetString(column_index); 
       } 
      } 
      finally 
      { 
       if (cursor != null) 
        cursor.Close(); 
      } 
      return null; 
     } 


     /** 
     * @param uri The Uri to check. 
     * @return Whether the Uri authority is ExternalStorageProvider. 
     */ 
     public static bool isExternalStorageDocument(Android.Net.Uri uri) 
     { 
      return "com.android.externalstorage.documents".Equals(uri.Authority); 
     } 

     /** 
     * @param uri The Uri to check. 
     * @return Whether the Uri authority is DownloadsProvider. 
     */ 
     public static bool isDownloadsDocument(Android.Net.Uri uri) 
     { 
      return "com.android.providers.downloads.documents".Equals(uri.Authority); 
     } 

     /** 
     * @param uri The Uri to check. 
     * @return Whether the Uri authority is MediaProvider. 
     */ 
     public static bool isMediaDocument(Android.Net.Uri uri) 
     { 
      return "com.android.providers.media.documents".Equals(uri.Authority); 
     } 
1

Обычно вы хотели бы проверить мим-тип элемента, выбранного, но это быстрый хак обработки элемента s, которые не в магазине СМИ:

string GetRealPathFromURI(Android.Net.Uri contentURI) 
{ 
    try 
    { 
     Android.Database.ICursor cursor = ContentResolver.Query(contentURI, null, null, null, null); 
     if (cursor != null) 
     { 
      cursor.MoveToFirst(); 
      string documentId = cursor.GetString(0); 
      documentId = documentId.Split(':')[1]; 
      cursor.Close(); 
      cursor = ContentResolver.Query(Android.Provider.MediaStore.Images.Media.ExternalContentUri, 
              null, 
              Android.Provider.MediaStore.Images.Media.InterfaceConsts.Id + " = ? ", new[] { documentId }, 
              null); 
      cursor.MoveToFirst(); 
      string path = cursor.GetString(cursor.GetColumnIndex(Android.Provider.MediaStore.Images.ImageColumns.Data)); 
      cursor.Close(); 
      return path; 
     } 
     return contentURI.Path; 
    } 
    catch (Android.Database.CursorIndexOutOfBoundsException ex) 
    { 
     return contentURI.Path; 
    } 
} 
+0

Спасибо, но это ошибка, когда я пытаюсь преобразовать его в байт [] .... System.IO.DirectoryNotFoundException: Не удалось найти часть пути «/document/primary:Test.pdf». –

+0

@AhmedAbdElhalem Вы имеете дело с 'document primary:' location, вам нужно будет использовать 'DocumentContracts' и проверять уровни SDK, вот хорошая отправная точка, чтобы показать, как вы имеете дело с' DocumentsContract', загружаемыми файлами и средопользователями файлы через «MediaProvider», он находится на Java, но быстро преобразуется в C#: http://stackoverflow.com/a/20559175/4984832 – SushiHangover

+0

Спасибо, его работы –