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

Redmi安卓10设备图片压缩时出现NullPointerException崩溃求助

Android 10 Redmi设备图片压缩代码NullPointerException排查与解决

崩溃信息

Failure delivering result ResultInfo{who=null, request=100, result=-1, data=Intent { act=inline-data (has extras) }} java.lang.NullPointerException

相关代码

public static Uri getImageUri(Context inContext, Bitmap inImage) {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();

    // Determine a size threshold below which compression is not performed
    int sizeThreshold = 1024; // for example, consider images smaller than 1KB

    if (inImage.getByteCount() > sizeThreshold) {
        inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
    } else {
        // Handle small images differently or skip compression
        // For example, you might simply use the original image without compression
        inImage.compress(Bitmap.CompressFormat.PNG, 100, bytes); // Use PNG format for small images
    }


    String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
    return Uri.parse(path);
}

问题分析

崩溃的直接原因是Uri.parse(path)触发NullPointerException——path为null,这是因为MediaStore.Images.Media.insertImage()在Android 10的Redmi设备上返回了null:

  • Android 10引入Scoped Storage,insertImage属于废弃API,在新存储策略下可能因写入权限限制、媒体库插入逻辑失败返回null;
  • Redmi定制ROM对媒体存储的额外管控,进一步放大了该API的兼容性问题;
  • 代码未对insertImage的返回值做空校验,直接传入Uri.parse()导致崩溃。

解决方案

1. 替换废弃API,适配Scoped Storage(推荐)

使用ContentResolver结合MediaStore的标准插入方式,完全兼容Android 10及以上版本:

public static Uri getImageUri(Context context, Bitmap bitmap) {
    // 自定义图片文件名和存储目录
    String displayName = "compressed_img_" + System.currentTimeMillis();
    String mimeType = bitmap.getByteCount() > 1024 ? "image/jpeg" : "image/png";
    ContentValues values = new ContentValues();
    
    values.put(MediaStore.Images.Media.DISPLAY_NAME, displayName);
    values.put(MediaStore.Images.Media.MIME_TYPE, mimeType);
    // 存储到应用专属图片目录,无需额外权限
    values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/YourApp");

    Uri uri = null;
    try {
        uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        if (uri != null) {
            try (OutputStream outputStream = context.getContentResolver().openOutputStream(uri)) {
                // 根据大小选择压缩格式
                if (bitmap.getByteCount() > 1024) {
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
                } else {
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
                }
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
        // 插入失败时清理无效Uri
        if (uri != null) {
            context.getContentResolver().delete(uri, null, null);
            uri = null;
        }
    }
    return uri;
}

2. 临时空值校验兼容

如果暂时无法替换API,必须增加空值校验避免NPE:

public static Uri getImageUri(Context inContext, Bitmap inImage) {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();

    int sizeThreshold = 1024;
    if (inImage.getByteCount() > sizeThreshold) {
        inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
    } else {
        inImage.compress(Bitmap.CompressFormat.PNG, 100, bytes);
    }

    String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
    // 空值校验,避免触发NPE
    if (path == null) {
        return null; // 上层调用时需处理null情况
    }
    return Uri.parse(path);
}

3. 权限适配

  • Android 10+:无需申请WRITE_EXTERNAL_STORAGE权限,Scoped Storage默认允许写入应用专属媒体目录;
  • Android 9及以下:需在Manifest中声明WRITE_EXTERNAL_STORAGE权限,并动态申请。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 23:25:30