Xamarin.Android 根据 Uri 获取文件路径

问题描述

需求

已获取 Android 文件的 Uri,现在需要根据此 Uri 获取文件的真实路径。比如:

 Image path == /storage/emulated/0/DCIM/Camera/IMG_20170813_223324.jpg

Code

private string GetActualPathFromFile(Android.Net.Uri uri)
{
    bool isKitKat = Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat;

    if (isKitKat && DocumentsContract.IsDocumentUri(this, uri))
    {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri))
        {
            string docId = DocumentsContract.GetDocumentId(uri);

            char[] chars = { ':' };
            string[] split = docId.Split(chars);
            string type = split[0];

            if ("primary".Equals(type, StringComparison.OrdinalIgnoreCase))
            {
                return Android.OS.Environment.ExternalStorageDirectory + "/" + split[1];
            }
        }
        // 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));

            //System.Diagnostics.Debug.WriteLine(contentUri.ToString());

            return getDataColumn(this, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri))
        {
            String docId = DocumentsContract.GetDocumentId(uri);

            char[] chars = { ':' };
            String[] split = docId.Split(chars);

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

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

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

        // Return the remote address
        if (isGooglePhotosUri(uri))
            return uri.LastPathSegment;

        return getDataColumn(this, 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;
    String column = "_data";
    String[] projection = 
    {
        column
    };

    try
    {
        cursor = context.ContentResolver.Query(uri, projection, selection, selectionArgs, null);
        if (cursor != null && cursor.MoveToFirst())
        {
            int index = cursor.GetColumnIndexOrThrow(column);
            return cursor.GetString(index);
        }
    }
    finally
    {
        if (cursor != null)
            cursor.Close();
    }
    return null;
}

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

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

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

//Whether the Uri authority is Google Photos.
public static bool isGooglePhotosUri(Android.Net.Uri uri)
{
    return "com.google.android.apps.photos.content".Equals(uri.Authority);
}

Usage

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
    if (requestCode == 0)
    {
        var uri = data.Data;
        string path = GetActualPathFromFile(uri);
        System.Diagnostics.Debug.WriteLine("Image path == " + path);
    }
}

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 132,016评论 20 560
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 7,430评论 1 40
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 9,834评论 2 43
  • 梦由象征和隐喻构建而成。隐喻能够造就美好、辉煌和奇妙的幻想。但我们必须坚持,如果被一个拥有错误生活方式但人所用,隐...
    Shuying0830阅读 11评论 0 0
  • 机器学习各优化算法的简单总结最全的机器学习优化算法介绍 常用的Adam:
    菜鸟瞎编阅读 30评论 0 0