2016-11-02 1 views
2

j'ai bouton pour joindre un fichierXamarin: GetRealPathFromURI travaille pour des images mais pas pour d'autres fichiers

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

Après avoir sélectionné un fichier, je peux obtenir le vrai chemin si elle est une image. Si ce n'est pas une image (PDF, DOCX), ça ne marche pas! Par exemple, voici le chemin de retour après avoir sélectionné une image:

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

mais après avoir sélectionné un fichier, cette erreur apparaît

Android.Database.CursorIndexOutOfBoundsException: Index 0 demandé, avec une taille de 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; 
     } 

Répondre

2

Ceci est la réponse

/** 
* 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

Normalement, vous voulez vérifier le mime-type de l'élément sélectionné, mais c'est un hack rapide de l'élément de manipulation s qui sont pas dans le magasin de médias:

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

Merci, mais cette erreur est survenue lorsque je tente de le convertir en octet [] .... System.IO.DirectoryNotFoundException: Impossible de trouver une partie du chemin "/document/primary:Test.pdf". –

+0

@AhmedAbdElhalem Vous avez affaire à 'document primaire:' emplacements, vous devrez utiliser 'DocumentContracts' et vérifier les niveaux SDK, voici un bon point de départ pour montrer comment vous gérez' DocumentsContract', les fichiers téléchargés, et mediastore-based fichiers via 'MediaProvider', il est en Java, mais il convertit rapidement en C#: http://stackoverflow.com/a/20559175/4984832 – SushiHangover

+0

Merci, ses travaux –