API30下Pixel Watch及模拟器Complication图标加载异常问题咨询
问题分析与解决方案
问题成因
API 30(Android R)之后,原生Wear OS对系统级Complication的资源访问策略做了调整:不再允许第三方表盘直接访问com.google.android.wearable.sysui包内的资源,而是通过Content Uri的方式提供图标资源。三星GW4因系统定制保留了兼容逻辑,所以能正常加载;但Pixel Watch和原生API30模拟器严格遵循新策略,导致直接调用loadDrawable()时触发PackageManager$NameNotFoundException。
解决方案
核心思路是优先使用Uri方式加载图标,同时兼容低版本系统:
- 替换图标加载逻辑,用
getIconUri()替代直接调用Icon.loadDrawable()
if (complicationData.getIcon() != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // API30+ 用Uri加载 Uri iconUri = complicationData.getIconUri(); if (iconUri != null) { try { drawable = Drawable.createFromStream( getContentResolver().openInputStream(iconUri), null ); } catch (IOException e) { e.printStackTrace(); // 加载失败时降级到默认图标 drawable = getResources().getDrawable(R.drawable.default_complication_icon); } } else { // 无Uri时尝试旧方法兜底 try { drawable = complicationData.getIcon().loadDrawable(getApplicationContext()); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); drawable = getResources().getDrawable(R.drawable.default_complication_icon); } } } else { // 低版本直接沿用原有逻辑 drawable = complicationData.getIcon().loadDrawable(getApplicationContext()); } icon[complicationId] = complicationData.getIcon(); }
- 其他图片方法的适配
针对getSmallImage()、getLargeImage()、getBurnInProtectionIcon(),同样用对应的Uri方法替代:
getSmallImageUri()getLargeImageUri()getBurnInProtectionIconUri()
适配逻辑和上述图标加载一致。
补充说明
三星Studio开发的表盘能正常显示,是因为其适配了三星定制系统的资源访问规则,而原生Wear OS要求第三方必须通过Content Uri访问系统Complication资源,这是文档未明确提及的API30+行为变更。
内容的提问来源于stack exchange,提问作者1Smart
相关产品推荐
相关产品推荐

