简体   繁体   English

如何使用 Xamarin.Android 中的 C# 找到所选图像的文件路径?

[英]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.我正在使用 Xamarin.Android 平台开发 Android 应用程序。 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".'我正在尝试从我的 Android 库中获取所选图像的文件路径,但我得到一个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.我希望根据图像文件路径将图像文件上传到块 Blob。 However, I am getting the System.IO.DirectoryNotFoundException: 'Could not find a part of the path "/document/image:2547".'但是,我得到了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.注意:请务必通过项目属性在Android 清单中的所需权限下授予READ_EXTERNAL_STORAGE 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.请记住将文件扩展名(例如 jpg)添加到path或您正在使用的任何变量。

You can refer to my another thread here , it should be helpful for you.您可以参考我的另一个帖子here ,它应该对您有所帮助。 The main code is as follows:主要代码如下:

method OnActivityResult方法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 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();
    }
 }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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