在没有bindAppWidgetId()的情况下将窗口小部件添加到启动器页面

我正在尝试将库存ICS启动器变成一个独立的应用程序。 我几乎就在那里 – 唯一不起作用的是搜索图标和将小部件放到屏幕上,这会导致崩溃。

崩溃是因为stock启动器使用appWidgetManager.bindAppWidgetId(appWidgetId, componentName); 添加小部件, 显然只有系统应用程序才有权限 。

所以我的问题是,非系统应用程序添加小部件并获得与库存ICS启动器相同的UI体验的正确方法是什么?

  • 单击小部件启动活动
  • 如何在Android主屏幕上制作4x1大小的小部件?
  • 动态启用或禁用窗口小部件不起作用
  • Android Widgets:RemoteViews上的animation?
  • 更改remoteView ImageView背景
  • 以编程方式显示/隐藏Flutter上的小部件
  • Gallery ImageAdapter convertView始终为null
  • 如何动态更新Widget(不等待30分钟才能调用onUpdate)?
  • Timmmm,

    你的问题是你正在寻找错误的对象。 你无法真正控制AppWidgetManager 。 它不是你的工作,它是系统的。 你可以做的是控制一个AppWidgetHost ,它只需要几个语义。 以下是基础知识。

    编辑:Widget绑定过程的额外背景

    AppWidgetManager是一个单独的对象,在系统启动时运行。 这意味着每个启动器的每个实例都使用相同的AppWidgetManager。 它们的区别在于它们的AppWidgetHost和它们目前持有的RemoteView。 AppWidgetManager基本上保留了所有活动主机及其持有的小部件的列表。 AppWidgetHost不是一个priveleged对象。 也就是说,任何活动都可能只有一个主机。 因此,如果他们愿意,整个应用程序可能只是Widgets。

    实例化主机时,必须先向其添加视图。 所以,基本上它是一个没有强制父母界限的子视图列表,除了你的Activity提供它。 首先,您要求一个ID(通过myHost.allocateAppWidgetId() )。 然后使用Pick Widget活动/对话框。 Dialog返回WidgetInfo。 当您要求主机使用WidgetInfo和您要求的ID创建View(通过createView )时,将检索View。 然后它会向小部件询问其RemoteView

    最后,通过将View作为子项放在Activity中来绑定窗口小部件。 这是通过ViewGroup的addView()方法完成的,该方法包含所有小部件。

    行动过程(EDITED)

    首先,你必须确保你的Android清单中有这个:

      

    接下来,你必须创建一个AppWidgetHost (我为我的启动器扩展自己的)。 Host的关键是通过AppWidgetManager.getInstance();保持对AppWidgetManager的引用AppWidgetManager.getInstance();

     AppWidgetHost myHost = new AppWidgetHost(context, SOME_NUMERICAL_CONSTANT_AS_AN_ID); 

    现在,获取您的ID:

     myHost.allocateAppWidgetId() 

    下一步是通过您用于获取小部件信息的任何方法完成的。 大多数情况下,它是通过onActivityResult通过Intent返回的。 现在,您真正需要做的就是使用appInfo并创建视图。 WidgetId通常由pick小部件活动结果提供。

     AppWidgetProviderInfo withWidgetInfo = AppWidgetManager.getInstance().getAppWidgetInfo(forWidgetId); AppWidgetHostView hostView = myWidgetHost.createView(myContext, forWidgetId, withWidgetInfo); hostView.setAppWidget(forWidgetId, withWidgetInfo); 

    现在,您只需将View作为子项绑定到要绑定它的任何内容。

     myViewGroup.addView(hostView); 

    当然,您始终必须考虑在何处以及如何放置它等。此外,在开始添加小部件之前,您必须确保AppWidgetHost正在侦听。

    myHost.startListening()

    总结一下

    Widget绑定过程涵盖了许多方法和步骤,但都通过AppWidgetHost 。 由于窗口小部件是在命名空间之外编码的,因此除了放置它们的位置以及如何调整视图外,您没有任何控件。 由于它们最终是在您的空间中运行但在您的控件之外的代码,因此AppWidgetManager充当中立调解器,而AppWidgetHost则代表您的应用程序的辅助器。 一旦理解了这一点,您的任务就很简单。 上述步骤是任何自定义启动程序(包括我自己的启动程序)所需的所有步骤。

    编辑:最终澄清

    ICS Launcher也是这样做的。 他们使用的appWidgetManager只是一个包含AppWidgetHostAppWidgetHost调用的包装器。 我忘了在Android Development Central网站上解释的很少。

    希望这可以帮助! 如果您需要更多细节,请告诉我。

    FuzzicalLogic

    我现在知道明确的答案。 在Android 4.0中,你不能这样做。 我最终让我的用户选择了两次小部件,这很糟糕,但没有办法解决它。

    在Android 4.1中他们解决了这个问题!

    SDK应用程序现在可以托管小部件,而不必使用垃圾小部件选择器API! 您可以查看Jellybean Launcher2源代码了解详细信息,但基本上,当您第一次尝试绑定窗口小部件时,Android会popup一个对话框,说“您是否要允许此应用程序绑定窗口小部件”,然后用户可以决定是否允许。

    我不确定他们为什么选择模态权限授予对话框而不是他们用于其他所有内容的所有权限安装模型,但无论如何,它都有效!

    现在我们只需等待4或5年,直到每个人都拥有Android 4.1或更高版本!

    我刚刚find了关于如何将appwidgets添加到普通应用程序的教程,这可能有所帮助: http : //coderender.blogspot.com/2012/01/hosting-android-widgets-my.html

    本教程仍然使用“AppWidget Picker”列表,因此它可能不适合您,因为ICS在应用程序抽屉内部具有小部件选择器。

    仍然值得一提,因为托管小部件的教程非常罕见:)

    干杯,
    Yuvi

    模糊逻辑,您的代码如下,

     AppWidgetProviderInfo withWidgetInfo = AppWidgetManager.getInstance().getAppWidgetInfo(forWidgetId); AppWidgetHostView hostView = myWidgetHost.createView(myContext, forWidgetId, withWidgetInfo); hostView.setAppWidget(forWidgetId, withWidgetInfo); 

    如果没有bind_widget的权限,widgethost什么都没有,cus withwidgetinfo为null,widgethost什么都不创建。