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

Android Oreo出现IOException: Resetting to invalid mark:一加5/5T图库图片缩放异常

解决OxygenOS 8.0.0上图片缩放抛出IOException: Resetting to invalid mark的问题

这个问题我之前在适配OnePlus机型时也碰到过,本质是OxygenOS 8.0.0的图库返回的InputStream不支持mark/reset机制,而相机拍摄的图片对应的流(比如FileInputStream)天然支持该机制,所以相机图能正常处理,图库图却报错。

问题根源

当你用BitmapFactory.decodeStream()或者自定义缩放逻辑调用了流的mark()和reset()时,如果原输入流不支持mark(或者标记的位置无效),就会抛出IOException: Resetting to invalid mark。OnePlus 5/5T的OxygenOS 8.0.0对图库文件的流做了定制,导致它不支持标准的mark/reset操作。

解决方案:将输入流转换为支持mark的ByteArrayInputStream

最稳妥的办法是先把图库返回的流读取成字节数组,再用ByteArrayInputStream包装——这个类天生支持mark/reset,不管原流是什么实现。

第一步:封装获取支持mark的流的方法

private InputStream getMarkSupportedInputStream(Context context, Uri imageUri) throws IOException {
    InputStream originalStream = context.getContentResolver().openInputStream(imageUri);
    if (originalStream == null) {
        return null;
    }

    // 将原流读取到字节数组
    ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int bytesRead;
    while ((bytesRead = originalStream.read(buffer)) != -1) {
        byteStream.write(buffer, 0, bytesRead);
    }
    originalStream.close();

    // 返回支持mark/reset的ByteArrayInputStream
    return new ByteArrayInputStream(byteStream.toByteArray());
}

第二步:修改你的缩放逻辑

把原来直接使用ContentResolver.openInputStream()的地方,换成上面的方法。比如完整的采样缩放代码:

public Bitmap getScaledBitmap(Context context, Uri imageUri, int targetWidth, int targetHeight) throws IOException {
    InputStream markSupportedStream = getMarkSupportedInputStream(context, imageUri);
    if (markSupportedStream == null) {
        return null;
    }

    BitmapFactory.Options options = new BitmapFactory.Options();
    // 先只获取图片尺寸,不加载完整Bitmap
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(markSupportedStream, null, options);

    // 重置流,因为上面的decodeStream已经读取了一部分内容
    markSupportedStream.reset();

    // 计算合适的采样率,避免OOM
    options.inSampleSize = calculateSampleSize(options, targetWidth, targetHeight);

    // 现在加载实际的Bitmap
    options.inJustDecodeBounds = false;
    Bitmap scaledBitmap = BitmapFactory.decodeStream(markSupportedStream, null, options);
    markSupportedStream.close();

    return scaledBitmap;
}

private int calculateSampleSize(BitmapFactory.Options options, int targetWidth, int targetHeight) {
    int originalWidth = options.outWidth;
    int originalHeight = options.outHeight;
    int sampleSize = 1;

    if (originalHeight > targetHeight || originalWidth > targetWidth) {
        int halfHeight = originalHeight / 2;
        int halfWidth = originalWidth / 2;

        while ((halfHeight / sampleSize) >= targetHeight && (halfWidth / sampleSize) >= targetWidth) {
            sampleSize *= 2;
        }
    }
    return sampleSize;
}

额外说明

  • 为什么Glide/Picasso一开始失效?这两个库内部也依赖流的mark/reset来处理图片,遇到OxygenOS的定制流时同样会触发异常,所以换自己的缩放方案时也会碰到同样的问题。
  • 内存注意事项:如果图片特别大,读取成字节数组可能会占用较多内存,这时候可以结合ParcelFileDescriptor和FileInputStream试试,但ByteArrayInputStream是兼容性最好的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:47:11