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

Android应用选取相册中相机拍摄的图片时崩溃,该如何解决?

崩溃核心原因分析

按出现概率从高到低排序:

  • 最常见原因是内存溢出(OOM):手机相机拍摄的原图分辨率普遍很高(多为4000万像素及以上),直接使用MediaStore.Images.Media.getBitmap加载完整原图,ARGB_8888格式下一张4000*3000分辨率的图片会占用48MB内存,很容易超出应用内存阈值触发崩溃,而普通相册图片/截图分辨率低,内存占用小所以运行正常。
  • 第二个常见原因是权限适配缺失:
    1. Android 6.0及以上系统,存储类权限需要动态申请用户授权,仅在Manifest静态声明不生效
    2. Android 13(API 33)及以上系统,原有READ_EXTERNAL_STORAGE权限已废弃,替换为READ_MEDIA_IMAGES权限,未适配会导致读取图片异常
  • 小概率为分区存储适配问题:Android 10及以上开启分区存储后,直接操作图片文件路径会触发权限错误,但你当前使用URI读取的写法本身是合规的,出现概率较低。

修复方案

1. 新增图片采样压缩逻辑,避免加载完整原图

替换原有getBitmap逻辑,先读取图片尺寸,按你的ImageView尺寸计算采样率,加载缩放后的位图,示例代码如下:

// 工具方法:从URI加载缩放后的位图
public Bitmap getScaledBitmapFromUri(Context context, Uri uri, int targetWidth, int targetHeight) throws IOException {
    ContentResolver resolver = context.getContentResolver();
    // 第一步:仅读取图片尺寸,不加载整张图到内存
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    InputStream inputStream = resolver.openInputStream(uri);
    BitmapFactory.decodeStream(inputStream, null, options);
    inputStream.close();
    // 计算采样率
    int width = options.outWidth;
    int height = options.outHeight;
    int inSampleSize = 1;
    if (height > targetHeight || width > targetWidth) {
        int halfHeight = height / 2;
        int halfWidth = width / 2;
        while ((halfHeight / inSampleSize) >= targetHeight && (halfWidth / inSampleSize) >= targetWidth) {
            inSampleSize *= 2;
        }
    }
    // 第二步:按采样率加载缩放后的位图
    options.inJustDecodeBounds = false;
    options.inSampleSize = inSampleSize;
    options.inPreferredConfig = Bitmap.Config.RGB_565; // 不需要透明度的话用这个格式,内存占用减少一半
    InputStream scaledInputStream = resolver.openInputStream(uri);
    Bitmap bitmap = BitmapFactory.decodeStream(scaledInputStream, null, options);
    scaledInputStream.close();
    return bitmap;
}

调用的时候传入你的ImageView的宽高即可:

// onActivityResult里替换原有getBitmap逻辑
bitmap = getScaledBitmapFromUri(this, selectedImage, imageView.getWidth(), imageView.getHeight());

2. 补全权限适配

在Manifest中更新权限声明:

<!-- 相机权限 -->
<uses-permission android:name="android.permission.CAMERA"/>
<!-- Android 12及以下读取存储权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- Android 13及以上读取图片权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

同时补充动态权限申请逻辑,用户授权后再调用选图方法。

3. 补充异常捕获

可以在现有catch块中新增OutOfMemoryError捕获,避免直接崩溃:

catch (OutOfMemoryError e) {
    e.printStackTrace();
    Toast.makeText(this, "图片加载失败,内存不足", Toast.LENGTH_SHORT).show();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:45:04