什么是App Widget
App Widget 是程序在桌面的插件。AppWidgetProviderInfo 对象为App Wiget 提供元数据,包括布局,更新频率等等的数据,这个对象被定义在XML 文件当中。AppWidgetProvider 定义了App Widget 的基本生命周期函数。
创建一个App Widget 的步骤
在res 文件夹下创建一个xml 子文件夹,创建一个名为example_appwidget_info.xml 的文件,插入<appwidget-provider ></appwidget-provider> 标签。android:updatePeriodMilis = "86400000" 代表更新的毫秒数。android:initalLayout= "@layout/example_appwidget" 代表的初始化的布局。
在layout 文件夹下创建一个example_widget.xml 文件,为App Widget 指定样式和布局。
在AndroidManifest.xml 文件中添加广播接收器:
<receiver
android:name="com.shumin.lbs17.ExampleAppWidgetProvider"
>
<intent-filter >
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>
</intent-filter>
<intent-filter >
<action android:name="com.shumin.lbs17.UPDATE_WIDGET"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/example_appwidget_info"/>
</receiver>
action 标签中引用的是安卓自带的命令,meta_data 代表元数据。
继承AppWidgetProvider 类,有以下方法:
onUpdate:在到达指定的更新时间之后或当用户向桌面添加AppWidget 时会调用该方法;
onDeleted:当App Widget 被删除时,会调用该方法;
onEnabled:当一个App Widget 的实例
第一次被创建时,会调用该方法;
onDisabled:当
最后一个App Widget 实例被删除后,会调用该方法;
onReceive:接收广播事件。
前面四个是声明周期方法。
什么是PandingIntent
就像锦囊,将Intent 包装进PendingIntent ,放进进程A,进程A 将包装了Intent 的PendingIntent 传递给进程B ,当有事件触发进程B 的时候,PendingIntent 执行。
创建PendingIntent 的方法,都是静态方法。
getActivity(Context context , int requestCode, Intent intent, int flags)
getBroadcast(Context context , int requestCode , Intent intent , int flags)
getService(Context context , int requestCode, Intent intent, int flags)
RemoteViews 的作用
1、RemoteViews 对象表示了一系列的View 对象。
2、RemoteViews 所表示的对象运行在另外的进程当中。
在App Widget 当中使用控件(Button)
在exmple_appwidget.xml 当中添加<Button />控件,由于App Widget 和我们的应用运行在不同的进程当中(App Widget 当中的View 运行在Home Screen 进程当中),所以无法按照之前管用的方法绑定监听器。
remoteViews.setOnClickPendingIntent(R.id.widgetButtonId,pendingIntent);
在实现了AppWidgetProvider 的类中,复写onUpdate 方法,通过for 循环……在for 循环中创建一个Intent 对象,通过调用PendingIntent 的getActivity 方法返回一个PendingIntent 对象(因为那些都是静态方法),创建一个RomoteViews 对象,调用setOnClickPendingIntent 方法,第一个参数用来指定被绑定处理器的控件ID,第二个参数指定当事件发生时,哪个PendingIntent 将会被执行。最后调用updateAppWidget 更新AppWidget 。
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
for (int i = 0; i < appWidgetIds.length; i++) {
System.out.println(appWidgetIds[i]);
Intent intent = new Intent(context, TargetActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context,0,intent,0);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.example_widget);
remoteViews.setOnClickPendingIntent(R.id.widgetbutton, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds[i], remoteViews);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
接受来自AppWidget 的广播
1、在AndroidManifest.xml 当中为AppWidgetProvider 注册新的int-fliter;
Intent 对象都通过onReceive 方法接收,由它根据Intent 对象中action 的值来决定调用哪个声明周期函数。
2、使用getBroadcast() 方法创建一个PendingIntent;
其实也就也是PendingIntent 调用了getBroadcast() 方法。
3、为AppWidget 当中的空间注册处理器;
4、在onReceive 方法当中接受广播消息。
更新AppWidget 当中的控件状态
由于AppWidget 和主程序不在同个进程当中,不能用普通方法进行操作。
在onReceive 方法中对remotViews 调用setXXXX 方法即可修改状态。修改完状态仍需要使appWidgetManager 调用updateAppWidget 方法更新,由于onReceive 方法中没有appWidgetManager 参数传入,故要在onReceive 方法中调用getInstance(context) 方法生成一个appWidgetManager 对象。
与RemoteViews 代表Widget 内所有控件不同,ComponentName 代表整个Wiget 。
public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if(UPDATE_ACTION.equals(action)){ RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.id.widgettextview); remoteViews.setTextViewText(R.id.widgettextview, "么么哒"); AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); ComponentName componentName = new ComponentName(context, ExampleAppWidgetProvider.class); appWidgetManager.updateAppWidget(componentName, remoteViews); }else{ super.onReceive(context, intent); } }