简体   繁体   中英

How do I find the file path to my selected image using C# in Xamarin.Android?

I am developing an Android application using the Xamarin.Android platform. I am deploying this to my device. I am trying to get the file path of a selected image from my Android gallery but I am getting a System.IO.DirectoryNotFoundException: 'Could not find a part of the path "/document/image:2547".' .

I have researched solutions for this but none of the solutions are helpful for my situation.

I will be excluding some code that is unnecessary to show.

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
    Android.Net.Uri uri = data.Data;
    string path = uri.Path;
    ImageView imageView = new ImageView(this);
    imageView.SetImageURI(uri);
    Blob.UploadFileInBlob(path);
}
public static class Blob
{
    public static async void UploadFileInBlob(string path)
    {
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse("[string here]");
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        CloudBlobContainer container = blobClient.GetContainerReference("images");
        await container.CreateIfNotExistsAsync();
        CloudBlockBlob blockBlob = container.GetBlockBlobReference("imageblob.jpg");
        await blockBlob.UploadFromFileAsync(@path);
    }
}

I expect the image file to be uploaded to the Block Blob based on the image file path. However, I am getting the System.IO.DirectoryNotFoundException: 'Could not find a part of the path "/document/image:2547".' error. The image itself still displays in the app when it is selected.

The following worked for me:

private void AddImage_Click(object sender, EventArgs args)
{
    Intent intent = new Intent();
    intent.SetType("image/*");
    intent.SetAction(Intent.ActionGetContent);
    StartActivityForResult(Intent.CreateChooser(intent, "Select Picture"), 1);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
    if ((requestCode == 1) && (resultCode == Result.Ok) && (data != null)
    {
        Android.Net.Uri uri = data.Data;
        string path = GetPathToImage(uri);
        Blob.UploadFileInBlob(path);
    }
}
private string GetPathToImage(Android.Net.Uri uri)
{
    ICursor cursor = ContentResolver.Query(uri, null, null, null, null);
    cursor.MoveToFirst();
    string document_id = cursor.GetString(0);
    if (document_id.Contains(":"))
        document_id = document_id.Split(':')[1];
    cursor.Close();

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

    return path;
}
public class Blob
{
    public static async void UploadFileInBlob(string path)
    {
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse("[string here]");
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        CloudBlobContainer container = blobClient.GetContainerReference("[Your container here]");
        await container.CreateIfNotExistsAsync();
        CloudBlockBlob blockBlob = container.GetBlockBlobReference("[Your Blob reference here]");
        await blockBlob.UploadFromFileAsync(path);
    }
}

Note: Be sure to grant READ_EXTERNAL_STORAGE under Required permissions in the Android Manifest through the project properties. Also, enable the Storage permission on your device for the app. Remember to add the file extension (eg jpg) to path or whatever variable you are using.

You can refer to my another thread here , it should be helpful for you. The main code is as follows:

method OnActivityResult

protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
        if (resultCode == Result.Canceled)
        {
            Finish();
        }
        else
        {
            try
            {
            var _uri = data.Data;
            var filePath = IOUtil.getPath(this, _uri);

            if (string.IsNullOrEmpty(filePath))
                filePath = _uri.Path;

            var file = IOUtil.readFile(filePath);// here we can get byte array
        }
            catch (Exception readEx)
            {
                System.Diagnostics.Debug.Write(readEx);
            }
            finally
            {
                Finish();
            }
    }
}

IOUtil.cs

public class IOUtil
{
  public static string getPath(Context context, Android.Net.Uri uri)
{
    bool isKitKat = Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat;

    // DocumentProvider
    if (isKitKat && DocumentsContract.IsDocumentUri(context, uri))
    {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri))
        {
            var docId = DocumentsContract.GetDocumentId(uri);
            string[] split = docId.Split(':');
            var 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 = DocumentsContract.GetDocumentId(uri);
            Android.Net.Uri contentUri = ContentUris.WithAppendedId(
                    Android.Net.Uri.Parse("content://downloads/public_downloads"), long.Parse(id));

            return getDataColumn(context, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri))
        {
            var docId = DocumentsContract.GetDocumentId(uri);
            string[] split = docId.Split(':');
            var 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;
            }

            var selection = "_id=?";
            var 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;
}

public static string getDataColumn(Context context, Android.Net.Uri uri, string selection,
string[] selectionArgs)
{

    ICursor cursor = null;
    var 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);
}

public static byte[] readFile(string file)
{
    try
    {
        return readFile(new File(file));
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.Write(ex);
        return new byte[0];
    }
 }

 public static byte[] readFile(File file)
 {
    // Open file
    var f = new RandomAccessFile(file, "r");

    try
    {
        // Get and check length
        long longlength = f.Length();
        var length = (int)longlength;

        if (length != longlength)
            throw new IOException("Filesize exceeds allowed size");
        // Read file and return data
        byte[] data = new byte[length];
        f.ReadFully(data);
        return data;
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.Write(ex);
        return new byte[0];
    }
    finally
    {
        f.Close();
    }
 }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM