没有(或最小)全局广播的Android Widget交互

时间:2013-02-24 17:36:13

标签: android android-widget static-members android-broadcast

我已经广泛搜索了这一内容,但未就此发现任何讨论。

Android AppWidgets(主屏幕小部件)不会通过LocalBroadcastManager接收本地应用程序广播(如果我错了,请更正)。因此,为了与小部件通信,我必须使用常规的系统广播。

许多来源建议,为了提高效率和安全性,只使用本地广播。我正在尝试找到一种与小部件进行通信的好方法,同时最大限度地减少全局广播的使用。

请让我知道任何有关探索的建议或资源,以便在解决此问题时进行检查,并评论我的暂定计划:

我目前的计划是将所有消息最小化为单个消息“WIDGET_NEEDS_UPDATE”。这基本上会“捅”小部件并告诉它查找更新信息。

我将把更新信息作为AppWidgetProvider的静态成员。因此,窗口小部件将接收此消息,然后从这些静态成员中读取操作以及执行操作所需的任何数据。

这看起来合理吗?

我还不确定静态成员的生命周期:只要应用程序活动或服务正在运行,我将保证能够访问这些静态成员吗​​?

非常感谢您的见解和指导。

2 个答案:

答案 0 :(得分:2)

  

Android AppWidgets(主屏幕小部件)不会通过LocalBroadcastManager接收本地应用程序广播(如果我错了,请更正)。因此,为了与小部件通信,我必须使用常规的系统广播。

AppWidgetProvider需要响应系统发送的广播,例如在首次添加(ACTION_APPWIDGET_UPDATE)时填充应用小部件的内容。

但是,您的代码(AppWidgetProvider之外)可以随时使用AppWidgetManagerupdateAppWidget()上的方法将更新推送到应用小部件的用户界面。推送这些更新的触发器取决于您,可以想象LocalBroadcastManager(或Otto或其他消息总线实现)可以发挥作用。

  

许多消息来源建议,为了提高效率和安全性,只使用本地广播。

App小部件本质上既不高效也不安全。如果您想要效率,请务必不要经常更新应用小部件。如果您需要安全性,请不要实现应用小部件。

“众多来源”正在为您提供一般性建议,主要是针对是发件人的情况而是这些广播的接收者,用于组件之间的通信你的应用。本地广播对于进程间通信是无用的,并且app小部件基于进程间通信。您的流程正在通过操作系统进程与主屏幕进程进行通信,以便将您的更改发送到主屏幕。

IOW,仅仅因为“很多来源”告诉你少吃,不要完全停止进食,因为这通常会导致问题。 : - )

  

我正在尝试找到一种与小部件进行通信的好方法,同时尽量减少使用全局广播。

您不“与小部件通信”。最多,您可以与AppWidgetProvider“沟通”。应用小部件本身是由主屏幕呈现的一组像素。

你无法摆脱系统广播(“全球广播”),因为无论你喜欢与否,操作系统都会发送它们,你需要它们才能使应用程序小部件正常工作。

  

我目前的计划是将所有消息最小化为单个消息“WIDGET_NEEDS_UPDATE”。

这将要求您重写Android操作系统,因为操作系统没有此广播的概念,并且无论您喜欢与否,它都会发送标准AppWidgetProvider广播。同样,您需要那些系统广播,否则您的应用小部件无法添加到屏幕上。

  

这基本上会“捅”小部件并告诉它查找更新信息。

通过AppWidgetManager更新应用小部件的用户界面会更高效。

  

这看起来合理吗?

你的安全性或效率都没有明显改善。

  

我还不确定静态成员的生命周期:只要应用程序活动或服务正在运行,我将保证能够访问这些静态成员吗​​?

没有。静态数据成员将一直存在,直到进程终止,这可能随时发生在不再处于前台的进程。

答案 1 :(得分:0)

我还需要向我的小部件发送安全广播。我的解决方案是在清单中声明第二个接收器:

<receiver android:name="com.yourpackage.widget.WidgetProvider" >
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>

        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/widget_info" />
    </receiver>
    <receiver
        android:name="com.yourpackage.widget.CustomReceiver"
        android:enabled="true"
        android:permission="com.youurpackage.appname.PERMISSION" >
        <intent-filter>
         <action android:name="com.youurpackage.appname.INIT_DONE" />
        </intent-filter>
    </receiver>

接收器类如下所示:

@Override
public void onReceive(Context context, Intent intent) {        
    if (intent.getAction().equals("com.youurpackage.appname.INIT_DONE")) {
        int[] ids = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, WidgetProvider.class));
        for (int widgetId : ids) {                
            AppWidgetManager.getInstance(context).updateAppWidget(widgetId, new RemoteViews(context.getPackageName(), R.layout.widget_layout));
            WidgetProvider.updateWidgetData(context, widgetId);
        }
    }
}

您还必须在清单中声明权限:

<permission
    android:name="com.youurpackage.appname.PERMISSION"
    android:description="@string/permission_description"
    android:label="@string/permission_name"
    android:protectionLevel="signature" >
</permission>

只有您的应用才能使用此权限发送广播。您可以发送广播  sendBroadcast(new Intent("com.youurpackage.appname.INIT_DONE"), "com.youurpackage.appname.PERMISSION");

如果这个解释足以理解我的建议,请告诉我。