Pre-Lollipop Android Widget中VectorDrawable使用及资源未找到异常问题
解决Pre-Lollipop Android Widget中VectorDrawable加载的Resources$NotFoundException问题
哥们儿,我太懂这种坑了——在API<21的Widget里用VectorDrawable简直是处处受限,app:srcCompat直接失效,编程加载还动不动报资源找不到,咱们一步步拆解问题解决:
第一步:先把兼容性配置拉满
首先得确保你的项目已经开启了VectorDrawable的支持库兼容,不然一切都是白搭:
- 在
app/build.gradle的defaultConfig里添加配置:
android { defaultConfig { vectorDrawables.useSupportLibrary = true } }
- 确认依赖的AppCompat/AndroidX库版本≥23.2.0(VectorDrawableCompat从这个版本开始正式支持RemoteViews场景)。
第二步:修正VectorDrawable的加载代码
RemoteViews不认直接的Drawable对象,必须转成Bitmap才能设置,而且加载方式必须用VectorDrawableCompat.create(),不能用系统原生的getDrawable()。给你一段经过验证的代码:
@Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { for (int appWidgetId : appWidgetIds) { RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.your_widget_layout); // 核心加载逻辑:用Application上下文,避免Activity上下文的资源问题 Resources res = context.getApplicationContext().getResources(); try { VectorDrawableCompat vectorDrawable = VectorDrawableCompat.create(res, R.drawable.water_drop_blue, null); if (vectorDrawable != null) { // 把VectorDrawable转成Bitmap,RemoteViews只认这个 Bitmap bitmap = Bitmap.createBitmap( vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888 ); Canvas canvas = new Canvas(bitmap); vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); vectorDrawable.draw(canvas); // 更新Widget里的ImageView remoteViews.setImageViewBitmap(R.id.your_widget_image_view, bitmap); } } catch (Resources.NotFoundException e) { e.printStackTrace(); } // 别忘了提交更新! appWidgetManager.updateAppWidget(appWidgetId, remoteViews); } }
这里要注意两个关键:
- 必须用Application上下文:Widget的生命周期和Activity无关,用Activity上下文容易导致资源加载异常
- 判空处理:
VectorDrawableCompat.create()可能返回null,一定要加判断避免崩溃
第三步:检查资源文件本身的问题
有时候不是代码的锅,是你的VectorDrawable文件有问题:
- 文件名必须是小写字母、数字、下划线/点,不能有大写或特殊字符(比如
WaterDropBlue.xml就不行,必须改成water_drop_blue.xml) - 用Android Studio的「Vector Asset」工具重新生成一遍资源,确保没有使用API<21不支持的属性(比如某些复杂的path指令)
- 确认资源放在
res/drawable/目录下,不是drawable-v21/(这个目录只有API≥21的系统才会识别)
第四步:排除混淆干扰
如果你的项目开启了混淆,一定要在proguard-rules.pro里添加保护规则,避免VectorDrawable相关类被混淆:
如果你用的是AppCompat库:
-keep class android.support.graphics.drawable.VectorDrawableCompat { *; } -keep class android.support.v7.widget.AppCompatDrawableManager { *; }
如果你用的是AndroidX:
-keep class androidx.core.graphics.drawable.VectorDrawableCompat { *; } -keep class androidx.appcompat.widget.AppCompatDrawableManager { *; }
按上面的步骤排查一遍,90%的概率能解决这个Resources$NotFoundException的问题。如果还是不行,你可以把报错的完整堆栈信息贴出来,咱们再深挖!
内容的提问来源于stack exchange,提问作者Aadil Mehraj
相关产品推荐
相关产品推荐

