You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android(Xamarin C#):如何获取插入图片路径以写入GPS EXIF信息

问题

我需要为通过ContentResolver.Insert()返回的Uri创建的图片添加GPS信息。我知道可以用ExifInterface写入GPS信息,但需要图片的路径,请问如何获取代码中的pathToSavedImage?(注:以下是Xamarin C#代码,Android相关解答同样适用)

核心代码示例

var cr = Application.Context.ContentResolver;
Android.Net.Uri uri = cr.Insert(MediaStore.Images.Media.ExternalContentUri, values);

Stream outputStream = cr.OpenOutputStream(uri, "w");
image.CopyTo(outputStream);
outputStream.Close();

// 需要获取pathToSavedImage来初始化ExifInterface
ExifInterface exifInterface = new ExifInterface(pathToSavedImage);
exifInterface.SetAttribute(key, value);
exifInterface.SaveAttributes();

补充的ContentValues配置

var values = new ContentValues();
values.Put(MediaStore.Images.Media.InterfaceConsts.Title, title);
values.Put(MediaStore.Images.Media.InterfaceConsts.DisplayName, name);
values.Put(MediaStore.Images.Media.InterfaceConsts.MimeType, "image/jpeg");
values.Put(MediaStore.Images.Media.InterfaceConsts.Description, description);
values.Put(MediaStore.Images.Media.InterfaceConsts.DateTaken, Java.Lang.JavaSystem.CurrentTimeMillis());

var album = Environment.DirectoryPictures + Java.IO.File.Separator + albumName;

values.Put(MediaStore.Images.Media.InterfaceConsts.RelativePath, album);
values.Put(MediaStore.Images.Media.InterfaceConsts.IsPending, true);

解决方案

方法一:通过ContentResolver查询获取图片路径

针对不同Android版本适配路径查询逻辑:

public string GetImagePathFromUri(Android.Net.Uri uri)
{
    string path = null;
    // 优先尝试查询DATA列(适用于Android 9及以下)
    string[] projection = { MediaStore.Images.Media.Data };
    
    using (var cursor = Application.Context.ContentResolver.Query(uri, projection, null, null, null))
    {
        if (cursor != null && cursor.MoveToFirst())
        {
            int columnIndex = cursor.GetColumnIndexOrThrow(MediaStore.Images.Media.Data);
            path = cursor.GetString(columnIndex);
            cursor.Close();
        }
    }
    
    // Android 10及以上,DATA列被隐藏,用RelativePath拼接完整路径
    if (string.IsNullOrEmpty(path) && Build.VERSION.SdkInt >= BuildVersionCodes.Q)
    {
        string[] projectionQ = { MediaStore.Images.Media.RelativePath, MediaStore.Images.Media.DisplayName };
        using (var cursor = Application.Context.ContentResolver.Query(uri, projectionQ, null, null, null))
        {
            if (cursor != null && cursor.MoveToFirst())
            {
                string relativePath = cursor.GetString(cursor.GetColumnIndexOrThrow(MediaStore.Images.Media.RelativePath));
                string fileName = cursor.GetString(cursor.GetColumnIndexOrThrow(MediaStore.Images.Media.DisplayName));
                path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/" + relativePath + "/" + fileName;
                cursor.Close();
            }
        }
    }
    
    return path;
}

使用方式:

string pathToSavedImage = GetImagePathFromUri(uri);
if (!string.IsNullOrEmpty(pathToSavedImage))
{
    ExifInterface exif = new ExifInterface(pathToSavedImage);
    // 设置GPS信息示例
    exif.SetAttribute(ExifInterface.TagGpsLatitude, "39.9042");
    exif.SetAttribute(ExifInterface.TagGpsLatitudeRef, "N");
    exif.SetAttribute(ExifInterface.TagGpsLongitude, "116.4074");
    exif.SetAttribute(ExifInterface.TagGpsLongitudeRef, "E");
    exif.SaveAttributes();
}

方法二:直接通过FileDescriptor操作Exif(推荐Android 10+)

Android 10及以上限制了直接文件路径访问,可通过ContentResolver打开FileDescriptor直接操作Exif,无需获取真实路径:

using (var fd = Application.Context.ContentResolver.OpenFileDescriptor(uri, "rw"))
{
    if (fd != null)
    {
        ExifInterface exif = new ExifInterface(fd.FileDescriptor);
        // 设置GPS信息
        exif.SetAttribute(ExifInterface.TagGpsLatitude, "39.9042");
        exif.SetAttribute(ExifInterface.TagGpsLatitudeRef, "N");
        exif.SetAttribute(ExifInterface.TagGpsLongitude, "116.4074");
        exif.SetAttribute(ExifInterface.TagGpsLongitudeRef, "E");
        exif.SaveAttributes();
        fd.Close();
    }
}

额外注意事项

你代码中设置了IsPending = true,写入完成后需要将其更新为false,确保媒体库能正常识别图片:

ContentValues updateValues = new ContentValues();
updateValues.Put(MediaStore.Images.Media.InterfaceConsts.IsPending, false);
Application.Context.ContentResolver.Update(uri, updateValues, null, null);

内容的提问来源于stack exchange,提问作者Shubham Agarwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 16:20:37