持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
问题描述
在实现通知栏相关需求时遇到了这个崩溃,测试机无法复现,只能试着解决。该崩溃字面意思是无法创建图标,检查了代码和相关资源,没有任何异常。通过搜索引擎可知,该BUG大概率是由通知栏构建器的setSmallIcon()引起的。关键代码如下:
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setOnlyAlertOnce(true)
.setWhen(System.currentTimeMillis())
.setShowWhen(true)
.setSmallIcon(R.mipmap.ic_logo);
曲折的DEBUG之路
-
将mipmap中的小图标放进drawable文件夹中,崩溃没有解决。
-
如果调用
setSmallIcon()时如果app还未启动,系统可能拿不到小图标的资源,此时可以用app自身的图标代替小图标,代码如下:
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
...
.setSmallIcon(context.getApplicationInfo().icon);
小图标确实变成了app的logo,但问题还是没有得到解决,反而崩溃更多了。
- 因为该通知栏使用了自定义布局,检查了
RemoteViews中的布局和所有的元素,都是符合RemoteViews规则的。假设该崩溃不是由setSmallIcon()引起的,而是app未启动时其他资源无法定位导致的。public.xml可以固定资源ID,不会被重新赋值,防止app未启动时调用资源时无法定位ID。在values文件夹中创建public.xml文件,将通知栏用到的所有资源都放进去,再通过public.xml中定义的资源id来引用。
<resources>
<item name="public_ic_logo_notification" type="drawable">@drawable/ic_logo_notification</item>
<item name="public_white" type="color">@color/white</item>
<item name="public_app_name" translatable="false" type="string">@string/app_name</item>
</resources>
问题仍旧得不到解决。
- 通过对该条崩溃的所有信息进行整理,发现崩溃都发生在Android7及以下系统。用Android7的手机进行测试,该崩溃可以被复现。在该手机上,app的图标是由系统提供的,而不是在
<application>中指定的logo。检查了各个mipmap文件夹,发现没有对低版本的系统进行图标适配。导致Android7以下系统通过context.getApplicationInfo().icon获取app图标失败,才出现了更多崩溃。对低版本系统进行图标适配后,该崩溃基本得到解决。
总结
- 通过
context.getApplicationInfo().icon获取app图标,需要图标对各个版本进行适配,使用Image Assert切割图标后记得检查mipmap各个文件夹中是否生成对应的图标。
- 注意
RemoteViews不要违规。