如何从BroadcastReceiver的Context获取colorSecondary主题属性?
这个问题我之前也碰到过,核心原因是BroadcastReceiver拿到的Context是ApplicationContext,而默认的Application主题往往没有应用包含colorSecondary的Material/AppCompat主题,导致resolveAttribute()找不到对应的属性,返回false。
接下来给你几个可行的解决方案:
方案1:给Application配置正确的主题
最根本的解决办法是确保你的Application使用的主题包含colorSecondary属性。在AndroidManifest.xml的<application>标签里指定主题:
<application ... android:theme="@style/AppTheme">
然后在res/values/styles.xml里定义AppTheme,继承自Material或AppCompat主题(确保主题自带或你自定义了colorSecondary):
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar"> <!-- 如果需要自定义secondary颜色,就加上这行 --> <item name="colorSecondary">@color/your_custom_secondary_color</item> </style>
这样ApplicationContext的主题就包含了colorSecondary,你的原方法getAttrColorResId()就能正常拿到资源ID了。
方案2:在BroadcastReceiver里使用带主题的ContextWrapper
如果不想修改Application的全局主题,或者需要临时使用特定主题,可以在BroadcastReceiver里创建一个ContextThemeWrapper,把原始Context包裹成带有目标主题的上下文:
// 在BroadcastReceiver的onReceive方法里 Context themedContext = new ContextThemeWrapper(context, R.style.AppTheme); // 然后用这个themedContext来获取颜色 int colorRes = getAttrColorResId(themedContext, R.attr.colorSecondary); // 或者直接获取颜色值(推荐,更稳定) int color = getAttrColor(themedContext, R.attr.colorSecondary);
这里推荐直接获取颜色值的方法,避免资源ID解析的问题,对应的工具方法可以改成:
public static int getAttrColor(Context context, @AttrRes int resId) { TypedArray typedArray = context.obtainStyledAttributes(new int[]{resId}); // 第二个参数是默认颜色,当属性找不到时返回这个值 int color = typedArray.getColor(0, android.R.color.darker_gray); typedArray.recycle(); // 记得回收TypedArray,避免内存泄漏 return color; }
方案3:直接引用颜色资源(应急方案)
如果以上方法都暂时没法用,也可以直接硬编码引用你的secondary颜色资源,比如:
int color = ContextCompat.getColor(context, R.color.your_secondary_color);
不过这种方法的缺点是无法跟随主题切换(比如深色/浅色模式),所以只适合临时应急,不推荐长期使用。
最后提醒一下:不管用哪种方案,都要确保你的主题里确实存在colorSecondary属性——Material主题默认自带,AppCompat主题需要你自己在style里定义哦。
内容的提问来源于stack exchange,提问作者Mangesh

