问题现象
1. 在MTK一些机器上,使用Bitmap这些保存到相册时,没有显示在图片最前面。
2. 国内的机器(如小米、荣耀)无此问题。
3. 环境是 MTK 的 Android 12 / 13
( 搜了全网没有找到正确的答案 )
问题分析
1. MTK机器原生相册根据date_taken做排序。
2. 国内的相册魔改已经不使用date_taken作为排序标准。
3. Bitmap存图流程不同系统生成流程,不会在图的exif信息中,自动产生DateTimeOriginal这个内容。
4. 使用网上的存图流程,可以从媒体库里看到并没有date_taken这个值。(在可root的机器中查看,路径是 /data/data/com.android.providers.media/databases)
5. exif中其实有挺多跟图片时间相关的字段:DateTimeOriginal / DateTimeDigitized 等
错误方式(当时找到最好的方式)
1. 以下这种方式可以把除date_taken以外的内容写进去。
2. 如果将第三步去掉,其实能在数据库看到有date_taken,但是这个pending的状态说明没有完成插入这个步骤,这时候图片在文件中是不可见的状态。
// 1. 先将数据插入数据库
values.put(MediaStore.Images.Media.IS_PENDING, 1);
uri = resolver.insert(Images.Media.EXTERNAL_CONTENT_URI, values);
// 2. 将数据写出到本地
outputStream = resolver.openOutputStream(uri);
outputStream.write(data);
// 3. 更新数据库
values.put(MediaStore.Images.Media.IS_PENDING, 0);
resolver.update(uri, values, null, null);
最终方案
核心代码
需要在插入数据库之前做操作
public static void modifyExif(String filePath, String newDateTime) {
try {
ExifInterface exif = new ExifInterface(filePath);
exif.setAttribute(ExifInterface.TAG_DATETIME_ORIGINAL, newDateTime);
exif.saveAttributes();
} catch (IOException e) {
e.printStackTrace();
}
}
使用示例
private Uri saveBitmapToGallery(Context context, byte[] imageBytes,
String filePath,String title,
long date,
Location location, int orientation) {
// 获取当前时间作为照片的拍摄时间
String ALBUM_FOLDER_NAME = "Camera";
// 创建文件路径
File albumDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM), ALBUM_FOLDER_NAME);
if (!albumDir.exists()) {
albumDir.mkdirs();
}
Uri uri = null;
File file = new File(filePath);
FileOutputStream outputStream = null;
try {
// 使用FileOutputStream写入数据
outputStream = new FileOutputStream(file);
outputStream.write(imageBytes);
outputStream.flush();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss", Locale.getDefault());
String newDateTime = sdf.format(new Date());
ExifModifier.modifyExif(filePath, newDateTime);
// 保存图片信息到媒体数据库
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
values.put(ImageColumns.TITLE, title);
values.put(ImageColumns.DISPLAY_NAME, title + ".jpg");
values.put(ImageColumns.DATE_MODIFIED, date / 1000);
// Clockwise rotation in degrees. 0, 90, 180, or 270.
values.put(ImageColumns.ORIENTATION, orientation);
if (location != null) {
values.put(ImageColumns.LATITUDE, location.getLatitude());
values.put(ImageColumns.LONGITUDE, location.getLongitude());
}
// 插入到相册
uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
// 更新系统图库(这是为了立即刷新图库,有些设备可能不需要这一步)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
} else {
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "saveBitmapToGallery error:" + e.getMessage());
} finally {
if(outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
return uri;
}