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

Android 12 三星A32设备Camera2保存图片损坏问题求助

问题根因

该故障是三星特定系统版本的硬件抽象层、系统媒体解码器容错性低,结合代码实现不严谨共同触发的,核心原因有两点:

  • JPEG数据读取逻辑存在兼容缺陷:现有代码直接读取Image对象planes[0]缓冲区的全部剩余字节写入文件,该逻辑在绝大多数设备上可正常运行,但SM-A326B在2022年6月安全补丁版本的Camera2 HAL存在实现差异:返回的JPEG格式Image的plane0缓冲区,在真实JPEG数据结束标记(0xFFD9)后附带了长度不等的内存填充垃圾数据。该设备原生系统图库、媒体解码器对JPEG格式校验严格,遇到结束标记后存在冗余数据的文件会直接判定为损坏,解码输出全白;第三方图片解码器通常会自动扫描定位JPEG结束标记截断数据,因此可以正常恢复显示。
  • EXIF写入逻辑不符合标准规范:现有saveExifData方法中,手动调用setAttribute给TAG_GPS_LATITUDE、TAG_GPS_LONGITUDE传入十进制度数字符串,不符合EXIF标准要求的「度:分:秒」有理数字符串格式。虽然后续调用了setLatLong()方法会尝试写入正确格式的经纬度数据,但该版本三星系统的ExifInterface实现不会覆盖同TAG的已有错误值,会把格式错误的GPS字段写入EXIF块,进一步提升系统解码器判定文件损坏的概率。
修复方案

可直接按以下步骤修改代码,全机型兼容:

  1. 修复JPEG数据读取逻辑,自动截断有效数据段
    替换原有直接读取全量缓冲区的逻辑,写入前先定位JPEG结束标记,只写入有效数据,修改后的saveCameraImage核心逻辑如下:
public void saveCameraImage(Image mImage, File mFile, String mOrientation, Context context) {
    ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
    byte[] bytes = new byte[buffer.remaining()];
    buffer.get(bytes);
    // 定位JPEG标准结束标记0xFFD9,截断HAL返回的冗余填充数据
    int jpegEndPos = bytes.length - 2;
    for (; jpegEndPos >= 0; jpegEndPos--) {
        if ((bytes[jpegEndPos] & 0xFF) == 0xD9 && (bytes[jpegEndPos - 1] & 0xFF) == 0xFF) {
            break;
        }
    }
    int validDataLength = jpegEndPos + 1;

    FileOutputStream fileOutputStream = null;
    try {
        fileOutputStream = new FileOutputStream(mFile);
        fileOutputStream.write(bytes, 0, validDataLength);
        // 主动刷新IO缓存,避免极端场景下写入不完整
        fileOutputStream.flush();
    } catch (IOException e) {
        wil.WriteFile("saveImage - Exception: " + e.getMessage(), context);
    } finally {
        mImage.close();
        if (null != fileOutputStream) {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                wil.WriteFile("saveImage - Exception: " + e.getMessage(), context);
            } finally {
                saveExifData(mFile.getPath(), context);
                createThumbs(mOrientation, mFile, context);
            }
        }
    }
}
  1. 移除错误的EXIF GPS字段手动赋值
    删除saveExifData方法中以下两行错误代码,setLatLong()是系统提供的标准API,会自动写入符合格式要求的经纬度字段,无需手动赋值:
// 删掉这两行
// exifInterface.setAttribute(ExifInterface.TAG_GPS_LATITUDE, String.valueOf(position.getLat()));
// exifInterface.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, String.valueOf(position.getLng()));
其他注意事项
  • 清单文件中<uses-feature android:name="android.hardware.location.gps " />配置项末尾存在多余空格,可能导致应用市场硬件特征匹配异常,建议删除该空格。
  • 建议将mImage.close()操作调整到字节数组读取、文件流写入完成之后执行,避免部分低版本OEM设备上缓冲区提前释放导致读取到脏数据。
验证方式
  • 修改后在故障设备上拍摄图片,校验生成的文件是否严格以0xFFD9结尾,系统图库可正常打开无全白、损坏提示
  • 回归验证其他机型的拍摄、保存、EXIF写入功能正常即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 14:31:14