3

我已经对此进行了广泛的搜索,但找不到任何关于此的讨论。

看来(如果我错了,请纠正我)Android AppWidgets(主屏幕小部件)没有通过 LocalBroadcastManager 接收本地应用程序广播。因此,要与小部件进行通信,我必须使用常规的系统范围广播。

许多来源建议仅使用本地广播以提高效率和安全性。我正在尝试找到一种与小部件进行通信的好方法,同时尽量减少全球广播的使用。

请让我知道在解决此问题时需要探索的任何建议或要检查的资源,并对我的暂定计划发表评论:

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

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

这看起来合理吗?

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

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

4

2 回答 2

2

看来(如果我错了,请纠正我)Android AppWidgets(主屏幕小部件)没有通过 LocalBroadcastManager 接收本地应用程序广播。因此,要与小部件进行通信,我必须使用常规的系统范围广播。

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

但是,您的代码AppWidgetProviderAppWidgetManager超出updateAppWidget(). 何时推送这些更新取决于您,并且可以想象LocalBroadcastManager(或 Otto 或其他消息总线实现)可以发挥作用。

许多来源建议仅使用本地广播以提高效率和安全性。

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

“许多来源”为您提供一般建议,主要是针对是发送者并且是那些广播的接收者以在应用程序组件之间进行通信的情况。本地广播对于进程间通信是无用的,而应用小部件是基于进程间通信的。您的进程正在通过 OS 系统进程与主屏幕进程通信,以将您的更改显示在主屏幕上。

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

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

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

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

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

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

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

仅通过AppWidgetManager.

这看起来合理吗?

您并没有明显提高安全性或效率。

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

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

于 2013-02-24T20:15:39.390 回答
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");

请让我知道这个解释是否足以理解我的建议。

于 2013-05-08T13:41:55.877 回答