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
相关产品推荐
相关产品推荐

