App Widget
应用程序窗口小部件,微型的应用程序视图,它可以被嵌入到其它应用程序中,比如桌面,并接收周期性的更新。你可以通过一个 App Widget Provider
来发布一个 Widget
。可以容纳 Widget
的应用叫做 App Widget Host
,详细参考 App Widgets| Android Developers
- 在
AndroidManifest
中声明App Widget
- 在
xml
目录定义App Widget
的初始化xml
文件 - 实现
Widget
具体布局的Layout xml
。 - 继承
AppWidgetProvider
类,实现具体的Widget
业务逻辑。
的 `android:name` 属性声明的就是 `Widget` 所用的 `AppWidgetProvider` 类,并且
中必须要包含 APPWIDGET_UPDATE
这个 `,所有
Widget 的
broadcast都是通过这个
filter` 来接收的。
声明了 `Widget` 的 `AppWidgetProviderInfo` 对应的资源 `xml` 的位置,用的是 `xml` 目录下的 `appwidget_provider.xml`。这里需要简单介绍下 `AppWidgetProviderInfo` 类,该类是用来描述 `Widget` 的 `meta` 信息,包括 `Widget` 的 `xml` 布局文件、刷新频率、最小宽高等等,而这些信息正是通过上述 `xml` 的
标签来描述的。
前面所说的用来描述 AppWidgetProviderInfo
的 xml
定义如下:
<?xml version="1.0" encoding="utf-8"?>
minWidth
&minHeight
:定义了Widget
的最小宽高,当minWidth
和minHeight
不是桌面cell
的整数倍时,Widget
的宽高会被阔至与其最接近的cells
大小。Google 官方给出了一个大致估算minWidth
&minHeight
的公式,根据Widget
所占的cell
数量来计算宽高:70 × n − 30
,n
是所占的cell
数量。updatePeriodMillis
:定义了Widget
的刷新频率,也就是App Widget Framework
多久请求一次AppWidgetProvider
的onUpdate()
回调函数。该时间间隔并不保证精确,出于节约用户电量的考虑,Android
系统默认最小更新周期是 30 分钟,也就是说:如果您的程序需要实时更新数据,设置这个更新周期是 2 秒,那么您的程序是不会每隔 2 秒就收到更新通知的,而是要等到 30 分钟以上才可以,要想实时的更新Widget
,一般可以采用Service
和AlarmManager
对Widget
进行更新。previewImage
:当用户选择添加Widget
时的预览图片。如果该属性没有定义,则展示application
的launcher icon
,该属性是在 3.0 以后引入的。initialLayout
:Widget
的布局Layout
文件。configure
:定义了用户在添加Widget
时弹出的配置页面的Activity
,用户可以在此进行Widget
的一些配置,该Activity
是可选的,如果不需要可以不进行声明。resizeMode
:Widget
在水平和垂直方向是否可以调整大小,值可以为:horizontal
(水平方向可以调整大小),vertical
(垂直方向可以调整大小),none
(不可以调整大小),也可以horizontal|vertical
组合表示水平和垂直方向均可以调整大小。widgetCategory
:表示Widget
可以显示的位置,包括home_screen
(桌面),keyboard
(锁屏),keyboard
属性需要 5.0 或以上 Android 版本才可以。
其它更多详细属性可以参考 AppWidgetProviderInfo。
AppWidgetProvider
继承自 BroadcastReceiver
,内部逻辑非常简单,就是在 onReceive()
中处理 Widget
相关的广播事件
ACTION_APPWIDGET_UPDATE
ACTION_APPWIDGET_DELETED
ACTION_APPWIDGET_ENABLED
ACTION_APPWIDGET_DISABLED
ACTION_APPWIDGET_OPTIONS_CHANGED
分发到各个回调函数中onUpdate()
, onDeleted()
, onEnabled()
, onDisabled
, onAppWidgetOptionsChanged()
。
onUpdate()
:是最重要的回调函数,根据updatePeriodMillis
定义的定期刷新操作会调用该函数,此外当用户添加Widget
时
也会调用该函数,可以在这里进行必要的初始化操作。但如果在` 中声明了
android:configure的
Activity,在用户添加
Widget时,不会调用
onUpdate(),需要由
configure Activity去负责去调用
AppWidgetManager.updateAppWidget()完成
Widget更新,后续的定时更新还是会继续调用
onUpdate()` 的。onDeleted()
:当Widget
被删除时调用该方法。onEnabled()
:当Widget
第一次被添加时调用,例如用户添加了两个你的Widget
,那么只有在添加第一个Widget
时该方法会被调用。所以该方法比较适合执行你所有Widgets
只需进行一次的操作。onDisabled()
:与onEnabled
恰好相反,当你的最后一个Widget
被删除时调用该方法,所以这里用来清理之前在onEnabled()
中进行的操作。onAppWidgetOptionsChanged()
:当Widget
第一次被添加或者大小发生变化时调用该方法,可以在此控制Widget
元素的显示和隐藏。
示例代码:
public class ExampleAppWidgetProvider extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
// Perform this loop procedure for each App Widget that belongs to this provider
for (int i=0; i
同时还需要在上述的 appwidget-provider
中声明:
有两点需要注意的是:
Activity
必须返回带EXTRA_APPWIDGET_ID
的result
。- 声明
Configuration Activity
后onUpdate()
在Widget
添加时不会被调用,Activity
负责调用AppWidgetManager.updateAppWidget()
完成Widget
更新。
具体步骤大致如下:
- 首先从
Activity
的Intent
中获取App Widget ID
Intent intent = getIntent(); Bundle extras = intent.getExtras(); if (extras != null) { mAppWidgetId = extras.getInt( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); }
- 执行你的
Widget
自定义配置逻辑 -
更新
App Widget
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.example_appwidget); appWidgetManager.updateAppWidget(mAppWidgetId, views);
- 设置
result Intent
,带上EXTRA_APPWIDGET_ID
,退出Activity
Intent resultValue = new Intent(); resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); setResult(RESULT_OK, resultValue); finish();