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

Android 12宿主应用加载小组件预览布局遇ResourcesNotFoundException

问题原因

previewLayout返回的是小组件提供应用内部的资源ID,每个Android应用的资源ID都是独立的,宿主应用的Context只能访问自身包内的资源,直接用宿主的LayoutInflater加载其他应用的资源ID,必然触发ResourcesNotFoundException。而loadPreviewImage是系统封装的跨应用资源加载方法,内部已处理跨包访问逻辑,所以能正常加载预览图。

解决方案

要加载其他应用的布局资源,必须先获取该应用的Context,再用这个跨应用的Context加载布局。具体步骤如下:

  1. 获取小组件应用的包名
    从AppWidgetProviderInfo的组件信息中提取包名:

    String widgetPackageName = widgetInfo.getAppWidgetInfo().provider.getPackageName();
    
  2. 创建小组件应用的Context
    使用createPackageContext方法创建对应包的Context,同时捕获包不存在的异常:

    Context widgetContext = null;
    try {
        // CONTEXT_RESTRICTED 创建受限Context,仅用于访问资源,避免权限风险
        widgetContext = binding.getRoot().getContext().createPackageContext(widgetPackageName, Context.CONTEXT_RESTRICTED);
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        // 小组件应用已卸载,降级到预览图逻辑
        if (previewDrawable != null) {
            Glide.with(binding.getRoot().getContext())
                 .load(previewDrawable)
                 .into(binding.previewImage);
        }
        return;
    }
    
  3. 用跨应用Context加载布局
    使用小组件应用的Context初始化LayoutInflater,再inflate目标布局:

    View widgetPreview = LayoutInflater.from(widgetContext).inflate(previewLayout, binding.getRoot(), false);
    binding.widgetContainer.addView(widgetPreview);
    
修改后的完整代码
Drawable previewDrawable = widgetInfo.getAppWidgetInfo().loadPreviewImage(binding.getRoot().getContext(), ICON_DENSITY);
int previewLayout = widgetInfo.getAppWidgetInfo().previewLayout;

try {
    if (previewLayout != 0) {
        String widgetPackageName = widgetInfo.getAppWidgetInfo().provider.getPackageName();
        Context widgetContext = binding.getRoot().getContext().createPackageContext(widgetPackageName, Context.CONTEXT_RESTRICTED);
        View widgetPreview = LayoutInflater.from(widgetContext).inflate(previewLayout, binding.getRoot(), false);
        binding.widgetContainer.addView(widgetPreview);
    } else if (previewDrawable != null) {
        Glide.with(binding.getRoot().getContext())
             .load(previewDrawable)
             .into(binding.previewImage);
    }
} catch (PackageManager.NameNotFoundException e) {
    // 小组件应用不存在,显示预览图或占位
    if (previewDrawable != null) {
        Glide.with(binding.getRoot().getContext())
             .load(previewDrawable)
             .into(binding.previewImage);
    }
    e.printStackTrace();
} catch (Exception e) {
    // 其他异常降级到预览图
    if (previewDrawable != null) {
        Glide.with(binding.getRoot().getContext())
             .load(previewDrawable)
             .into(binding.previewImage);
    }
    e.printStackTrace();
}
注意事项
  • 如果小组件应用的资源设置了android:private="true",宿主应用将无法访问这些资源,此时只能降级使用previewImage。
  • Android 12及以上版本中,CONTEXT_RESTRICTED是更安全的选项,它限制了Context的权限,仅允许访问资源,避免潜在的安全风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 12:55:24