Reputation: 41
I have button to attach a file
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);
}
After selecting a file, I can get the real path if it is an image. If it is not an image (PDF, DOCX), it does not work! For example, here is the path returned after selecting an image:
"/storage/0403-0201/Pictures/beach_huts.jpg"
but after selecting a file, this error appears
Android.Database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 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;
}
Upvotes: 2
Views: 1279
Reputation: 41
This is the Answer
/**
* 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);
}
Upvotes: 2
Reputation: 74144
Normally you would want to check the mime-type of the item selected, but this is a quick hack of handling items that are not in the media store:
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;
}
}
Upvotes: 1