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

Android 8+设备触发NullPointerException:调用Drawable.isProjected()对象为空求助

解决Android 8.0+三星/华为设备上的AdaptiveIconDrawable NullPointerException问题

从你描述的情况和Fabric日志来看,这个异常是Android 8.0引入自适应图标(AdaptiveIconDrawable)后,三星、华为这类定制ROM在图标处理上的边界case导致的——当系统调用AdaptiveIconDrawable.isProjected()时,Drawable对象为空,触发了空指针异常。下面是几个经过验证的解决方案:

1. 安全获取应用图标,添加兜底逻辑

首先要确保从PackageManager获取应用图标时不会返回null,并且在获取失败时用默认图标兜底:

public Drawable getAppIcon(Context context, String packageName) {
    PackageManager pm = context.getPackageManager();
    Drawable appIcon = null;
    try {
        ApplicationInfo info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
        appIcon = info.loadIcon(pm);
    } catch (PackageManager.NameNotFoundException e) {
        Log.e("AppIconLoader", "Failed to load icon for " + packageName, e);
    }
    // 兜底:如果获取到的图标为空,使用默认图标替代
    if (appIcon == null) {
        appIcon = ContextCompat.getDrawable(context, R.drawable.ic_default_app_icon);
    }
    return appIcon;
}

2. 将AdaptiveIconDrawable转换为BitmapDrawable

部分定制ROM的AdaptiveIconDrawable实现存在缺陷,直接使用容易触发内部空指针。把它转换成BitmapDrawable可以绕过系统的特殊处理逻辑:

private Drawable convertAdaptiveIconToBitmap(Context context, Drawable icon) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && icon instanceof AdaptiveIconDrawable) {
        Bitmap bitmap = Bitmap.createBitmap(icon.getIntrinsicWidth(), icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        icon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        icon.draw(canvas);
        return new BitmapDrawable(context.getResources(), bitmap);
    }
    return icon;
}

在给RecyclerView的ImageView设置图标前,调用这个转换方法:

Drawable icon = getAppIcon(context, appInfo.packageName);
icon = convertAdaptiveIconToBitmap(context, icon);
holder.appIconImageView.setImageDrawable(icon);

3. 检查RecyclerView Item布局的背景设置

如果你的Item布局中某个View的background使用了自适应图标或动态设置Drawable,要确保不会设置为null。比如避免直接调用view.setBackgroundDrawable(null),而是替换为设置透明背景或默认背景。

额外建议

  • 优先在三星、华为的Android 8.0+设备上做针对性测试,覆盖系统应用、第三方应用、带自适应图标的应用等不同场景
  • 可以尝试用PackageManager.getDrawable()替代loadIcon(),部分ROM下这个方法的稳定性更好

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:37:23