1.建立AppWidget
1.1 在res/xml/widget_test.layout
<appwidget-provider xmlns:android=" http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/album_appwidget" //你想创建的widget界面的布局文件,还不支持自定义控件
android:minHeight="72dp"
android:minWidth="144dip"//控制widget的大小
android:updatePeriodMillis="86400000" >
</appwidget-provider>
1.2创建 Hellowidget extends AppWidgetProvider并处理各个周期方法
onReceive onUpdate onEnabled onDisabled onDeleted
AppWidgetProvider本身就是一个广播接收者,监听了开机广播android.intent.action.BOOT_COMPLETED
所以widget开机是可以用的
1.3 在AndroidManifest.xml文件中注册
<receiver
android:name=".Hellowidget"
android:label="@string/widget_text" >
<intent-filter android:priority="1000">
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/appwidget_info" />
</receiver>
1.4 各种情况下的周期方法的处理
1.4.0.安装apk widget就会走这两个生命周期onReceive-onUpData
1.4.1.创建widget onReceive-onUpData
1.4.2.删除widget onReceive-onDeleted
1.4.3.桌面上有widget onReceive-onEnabled-onReceive-onUpData
1.4.4.桌面上没有widget onReceive-onEnabled-onReceive-onUpData
1.4.5. onReceive 方法里面接收各种广播,可以打印action查看
onUpData AppWidgetManager.ACTION_APPWIDGET_UPDATE
中调用响应时的ACTION_APPWIDGET_UPDATE广播此AppWidget提供者被要求提供RemoteViews
关键代码:
RemoteViews views=new RemoteViews(context.getPackageName(),R.layout.album_appwidget);
if(appWidgetIds==null){
appWidgetManager.updateAppWidget(new ComponentName(context,this.getClass()), views);
}else{
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
初始化界面控件的点击事件处理
Intent mIntent;
PendingIntent mPendingIntent;
mIntent=new Intent(HellowidgetServer.SERVICECMD);
mPendingIntent=PendingIntent.getBroadcast(context, 0, mIntent, 0);
views.setOnClickPendingIntent(R.id.control_play, mPendingIntent);
RemoteViews提供的了对其全部的控件设置点击事件和图片,文字,都是通过viewid识别是哪一个view
views.setTextViewText(int viewid,String content);
onEnabled AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)
onDeleted AppWidgetManager.ACTION_APPWIDGET_DELETED
1.5 appwidget一般结合Service使用,通过Service实现逻辑处理 以google android音乐播放器源码为例为例
1.5.1 MediaAppWidgetProvider widget类
MediaPlaybackService 后台逻辑Service
1.5.2 当处理完点击事件的时候,并且保证后台服务的启动
intent = new Intent(MediaPlaybackService.TOGGLEPAUSE_ACTION);
intent.setComponent(serviceName);
pendingIntent = PendingIntent.getService(context,
0 /* no requestCode */, intent, 0 /* no flags */);
views.setOnClickPendingIntent(R.id.control_play, pendingIntent);//这里启动的是发送一个广播
对应后台逻辑Service onCreate里面注册的服务
IntentFilter commandFilter = new IntentFilter();
commandFilter.addAction(SERVICECMD);
commandFilter.addAction(TOGGLEPAUSE_ACTION);
commandFilter.addAction(PAUSE_ACTION);
commandFilter.addAction(NEXT_ACTION);
commandFilter.addAction(PREVIOUS_ACTION);
registerReceiver(mIntentReceiver, commandFilter);
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String cmd = intent.getStringExtra("command");
if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {
next(true);//调用服务的方法
} else if (CMDPREVIOUS.equals(cmd) || PREVIOUS_ACTION.equals(action)) {
prev();//调用服务的方法
}
}
};
1.6 对于widget数据更新,还是以google android音乐播放器源码
在 MediaPlaybackService 中通过MediaAppWidgetProvider对外提供的获取实例的方法获取对象
#MediaAppWidgetProvider类中
static synchronized MediaAppWidgetProvider getInstance() {
if (sInstance == null) {
sInstance = new MediaAppWidgetProvider();
}
return sInstance;
}
#MediaPlaybackService
private MediaAppWidgetProvider mAppWidgetProvider = MediaAppWidgetProvider.getInstance();
当播放下一首,或者暂停的时候都会更换widget界面的信息
mAppWidgetProvider.notifyChange(this, what);
#MediaAppWidgetProvider
void notifyChange(MediaPlaybackService service, String what) {
if (hasInstances(service)) {
if (MediaPlaybackService.META_CHANGED.equals(what) ||
MediaPlaybackService.PLAYSTATE_CHANGED.equals(what)) {
performUpdate(service, null);
}
}
}
void performUpdate(MediaPlaybackService service, int[] appWidgetIds) {
final Resources res = service.getResources();
final RemoteViews views = new RemoteViews(service.getPackageName(), R.layout.album_appwidget);
CharSequence titleName = service.getTrackName();
CharSequence artistName = service.getArtistName();
CharSequence errorState = null;
。。。。。。。。。。。。。//更新界面代码
// No error, so show normal titles
views.setViewVisibility(R.id.title, View.VISIBLE);
views.setTextViewText(R.id.title, titleName);
views.setTextViewText(R.id.artist, artistName);
}
1.7 京东商城android widget
@1.没有创建widget的时候,后台服务不起来
@2.widget被删除的时候,后台服务停止, 生命周期相同
在onReceive方法中获取appWidgetInfo是否有与保存在本地信息匹配,
如果有的那就启动后台的线程,如果没有的那就不启动,提高用户体验,避免创建不必要的后台服务,
AppWidgetManager instance = AppWidgetManager.getInstance(context);
int[] appWidgetIds2 =instance.getAppWidgetIds(new ComponentName(context,this.getClass()));
AppWidgetProviderInfo appWidgetInfo = instance.getAppWidgetInfo(appWidgetIds2[0]);
// appWidgetInfo.label
这里提供一个别人的桌面widget的好例子( 例子下载)
http://www.eoeandroid.com/forum.php?mod=viewthread&tid=164878
1.1 在res/xml/widget_test.layout
<appwidget-provider xmlns:android=" http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/album_appwidget" //你想创建的widget界面的布局文件,还不支持自定义控件
android:minHeight="72dp"
android:minWidth="144dip"//控制widget的大小
android:updatePeriodMillis="86400000" >
</appwidget-provider>
1.2创建 Hellowidget extends AppWidgetProvider并处理各个周期方法
onReceive onUpdate onEnabled onDisabled onDeleted
AppWidgetProvider本身就是一个广播接收者,监听了开机广播android.intent.action.BOOT_COMPLETED
所以widget开机是可以用的
1.3 在AndroidManifest.xml文件中注册
<receiver
android:name=".Hellowidget"
android:label="@string/widget_text" >
<intent-filter android:priority="1000">
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/appwidget_info" />
</receiver>
1.4 各种情况下的周期方法的处理
1.4.0.安装apk widget就会走这两个生命周期onReceive-onUpData
1.4.1.创建widget onReceive-onUpData
1.4.2.删除widget onReceive-onDeleted
1.4.3.桌面上有widget onReceive-onEnabled-onReceive-onUpData
1.4.4.桌面上没有widget onReceive-onEnabled-onReceive-onUpData
1.4.5. onReceive 方法里面接收各种广播,可以打印action查看
onUpData AppWidgetManager.ACTION_APPWIDGET_UPDATE
中调用响应时的ACTION_APPWIDGET_UPDATE广播此AppWidget提供者被要求提供RemoteViews
关键代码:
RemoteViews views=new RemoteViews(context.getPackageName(),R.layout.album_appwidget);
if(appWidgetIds==null){
appWidgetManager.updateAppWidget(new ComponentName(context,this.getClass()), views);
}else{
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
初始化界面控件的点击事件处理
Intent mIntent;
PendingIntent mPendingIntent;
mIntent=new Intent(HellowidgetServer.SERVICECMD);
mPendingIntent=PendingIntent.getBroadcast(context, 0, mIntent, 0);
views.setOnClickPendingIntent(R.id.control_play, mPendingIntent);
RemoteViews提供的了对其全部的控件设置点击事件和图片,文字,都是通过viewid识别是哪一个view
views.setTextViewText(int viewid,String content);
onEnabled AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)
onDeleted AppWidgetManager.ACTION_APPWIDGET_DELETED
1.5 appwidget一般结合Service使用,通过Service实现逻辑处理 以google android音乐播放器源码为例为例
1.5.1 MediaAppWidgetProvider widget类
MediaPlaybackService 后台逻辑Service
1.5.2 当处理完点击事件的时候,并且保证后台服务的启动
intent = new Intent(MediaPlaybackService.TOGGLEPAUSE_ACTION);
intent.setComponent(serviceName);
pendingIntent = PendingIntent.getService(context,
0 /* no requestCode */, intent, 0 /* no flags */);
views.setOnClickPendingIntent(R.id.control_play, pendingIntent);//这里启动的是发送一个广播
对应后台逻辑Service onCreate里面注册的服务
IntentFilter commandFilter = new IntentFilter();
commandFilter.addAction(SERVICECMD);
commandFilter.addAction(TOGGLEPAUSE_ACTION);
commandFilter.addAction(PAUSE_ACTION);
commandFilter.addAction(NEXT_ACTION);
commandFilter.addAction(PREVIOUS_ACTION);
registerReceiver(mIntentReceiver, commandFilter);
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String cmd = intent.getStringExtra("command");
if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {
next(true);//调用服务的方法
} else if (CMDPREVIOUS.equals(cmd) || PREVIOUS_ACTION.equals(action)) {
prev();//调用服务的方法
}
}
};
1.6 对于widget数据更新,还是以google android音乐播放器源码
在 MediaPlaybackService 中通过MediaAppWidgetProvider对外提供的获取实例的方法获取对象
#MediaAppWidgetProvider类中
static synchronized MediaAppWidgetProvider getInstance() {
if (sInstance == null) {
sInstance = new MediaAppWidgetProvider();
}
return sInstance;
}
#MediaPlaybackService
private MediaAppWidgetProvider mAppWidgetProvider = MediaAppWidgetProvider.getInstance();
当播放下一首,或者暂停的时候都会更换widget界面的信息
mAppWidgetProvider.notifyChange(this, what);
#MediaAppWidgetProvider
void notifyChange(MediaPlaybackService service, String what) {
if (hasInstances(service)) {
if (MediaPlaybackService.META_CHANGED.equals(what) ||
MediaPlaybackService.PLAYSTATE_CHANGED.equals(what)) {
performUpdate(service, null);
}
}
}
void performUpdate(MediaPlaybackService service, int[] appWidgetIds) {
final Resources res = service.getResources();
final RemoteViews views = new RemoteViews(service.getPackageName(), R.layout.album_appwidget);
CharSequence titleName = service.getTrackName();
CharSequence artistName = service.getArtistName();
CharSequence errorState = null;
。。。。。。。。。。。。。//更新界面代码
// No error, so show normal titles
views.setViewVisibility(R.id.title, View.VISIBLE);
views.setTextViewText(R.id.title, titleName);
views.setTextViewText(R.id.artist, artistName);
}
1.7 京东商城android widget
@1.没有创建widget的时候,后台服务不起来
@2.widget被删除的时候,后台服务停止, 生命周期相同
在onReceive方法中获取appWidgetInfo是否有与保存在本地信息匹配,
如果有的那就启动后台的线程,如果没有的那就不启动,提高用户体验,避免创建不必要的后台服务,
AppWidgetManager instance = AppWidgetManager.getInstance(context);
int[] appWidgetIds2 =instance.getAppWidgetIds(new ComponentName(context,this.getClass()));
AppWidgetProviderInfo appWidgetInfo = instance.getAppWidgetInfo(appWidgetIds2[0]);
// appWidgetInfo.label
这里提供一个别人的桌面widget的好例子( 例子下载)
http://www.eoeandroid.com/forum.php?mod=viewthread&tid=164878