我已经广泛搜索了这一内容,但未就此发现任何讨论。
Android AppWidgets(主屏幕小部件)不会通过LocalBroadcastManager接收本地应用程序广播(如果我错了,请更正)。因此,为了与小部件通信,我必须使用常规的系统广播。
许多来源建议,为了提高效率和安全性,只使用本地广播。我正在尝试找到一种与小部件进行通信的好方法,同时最大限度地减少全局广播的使用。
请让我知道任何有关探索的建议或资源,以便在解决此问题时进行检查,并评论我的暂定计划:
我目前的计划是将所有消息最小化为单个消息“WIDGET_NEEDS_UPDATE”。这基本上会“捅”小部件并告诉它查找更新信息。
我将把更新信息作为AppWidgetProvider的静态成员。因此,窗口小部件将接收此消息,然后从这些静态成员中读取操作以及执行操作所需的任何数据。
这看起来合理吗?
我还不确定静态成员的生命周期:只要应用程序活动或服务正在运行,我将保证能够访问这些静态成员吗?
非常感谢您的见解和指导。
答案 0 :(得分:2)
Android AppWidgets(主屏幕小部件)不会通过LocalBroadcastManager接收本地应用程序广播(如果我错了,请更正)。因此,为了与小部件通信,我必须使用常规的系统广播。
AppWidgetProvider
需要响应系统发送的广播,例如在首次添加(ACTION_APPWIDGET_UPDATE
)时填充应用小部件的内容。
但是,您的代码(AppWidgetProvider
之外)可以随时使用AppWidgetManager
及updateAppWidget()
上的方法将更新推送到应用小部件的用户界面。推送这些更新的触发器取决于您,可以想象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");
如果这个解释足以理解我的建议,请告诉我。