试着写一个音乐播放器的桌面控件,练习下前三篇的内容。
假定现在有一个 MusicService.class 来实现对音乐播放 的控制。我们需要做的是:写一个 app widget 包含当前音乐封面、歌曲名、歌手名、上下一曲、暂停播放的按钮。通过按钮发送对应的广播,然后 MusicService 接收广播消息实现对播放的控制。
分析:appwidget 监听桌面按钮,然后根据按钮的不同,发送不同的广播指令给 MusicService ,MusicService 收到指令后 按照指令的不同,实现不同的功能(如上下一曲、暂停播放等)并远程更新 appwidget 的显示(当前歌曲封面、歌曲名、歌手名、播放/暂停显示 等)。
步骤:
1. 在 layout 文件夹下创建 appwidght.xml 文件。在里面写入你的 app widght 布局
android:layout_height="fill_parent"
android:orientation="horizontal" >
android:layout_width="60dip"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:src="@drawable/ic_launcher" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:paddingTop="6dip"
android:layout_toRightOf="@id/appwidget_image"
android:text="music name"
/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:paddingBottom="6dip"
android:layout_toRightOf="@id/appwidget_image"
android:text="singer name"
/>
效果如下(演示时加上了红色背景填充,最后手动换成了透明图标。):
2. 在 res 目录下创建 xml 文件夹。并在 res/xml 文件夹下创建 app_widght.xml 文件。在文件里写入如下内容:
android:minWidth="300dip"
android:minHeight="60dip"
android:updatePeriodMillis="43200000"
android:initialLayout="@layout/appwidget">
3. 创建类 MyAppWidget 并继承 AppWidgetProvider 。然后重写里面的 onUpdate() 方法。
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
for(int i = 0; i < appWidgetIds.length; i++){
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.appwidget);
Intent last_intent = new Intent();
last_intent.setAction("last");
PendingIntent last_pendingIntent = PendingIntent.getBroadcast(context, 0, last_intent, 0);
remoteViews.setOnClickPendingIntent(R.id.appwidget_button_last, last_pendingIntent);
Intent play_intent = new Intent();
play_intent.setAction("play");
PendingIntent play_pendingIntent = PendingIntent.getBroadcast(context, 0, play_intent, 0);
remoteViews.setOnClickPendingIntent(R.id.appwidget_button_play, play_pendingIntent);
Intent next_intent = new Intent();
next_intent.setAction("next");
PendingIntent next_pendingIntent = PendingIntent.getBroadcast(context, 0, next_intent, 0);
remoteViews.setOnClickPendingIntent(R.id.appwidget_button_next, next_pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds[i], remoteViews);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
至此,监听按钮并发送给 MusicService 的功能已经实现了。(如果谁知道这段重复代码怎么消灭,请不吝赐教,谢谢。)
4. 功能写完了,但是,千万千万别忘了 在AndroidManifest.xml 里注册一下 app widget 的 revice。
至此,app widget 的使命就算是完成了。接下来就是 服务端(MusicService )的工作了。
5. MusicService 接收 并更新 app widget 的图标和文字。
(1) 首先动态注册一个 BroadcastReceiver ,用来监听 app widget 发送的三个广播 代码如下:
private Broadcast_Receiver receiver;
receiver = new Broadcast_Receiver();
IntentFilter filter = new IntentFilter();
filter.addAction("last");
filter.addAction("next");
filter.addAction("play");
this.registerReceiver(receiver, filter);
(2) 在 MusicService 里创建一个 Broadcast_Receiver extends BroadcastReceiver 的内部类(内部类可以自由使用 MusicService 的属性和方法)。代码如下:
public class Broadcast_Receiver extends BroadcastReceiver {
private Context context;
@Override
public void onReceive(Context context, Intent intent) {
this.context = context;
// 获取action标记,用与区分点击事件
String ctrl_code = intent.getAction();
if ("play".equals(ctrl_code)) {
播放音乐()/暂停播放();
}
}else if ("next".equals(ctrl_code)) {
下一曲();
} else if ("last".equals(ctrl_code)) {
上一曲();
}
}
}
汉字部分,应使用 MusicService 现成的方法。(别告诉我你音乐服务里没有具体播放的方法...)
(3) 发广播提示 app widget 更新图片和文字显示。
在 MusicService 里需要更新 ui 时,调用 uodateAppWidget() 方法,方法代码如下:
public void updateAppWidget(){
Bundle bundle = new Bundle();
bundle.putStringArray("data", musicData);
bundle.putParcelable("bitmap",bmp);
Intent intent = new Intent();
intent.setAction("update_appwidget");
intent.putExtras(bundle);
sendBroadcast(intent);
}
其中,musicData 是包含了 正在播放的歌曲名和歌手名的数组。 bmp 是当前歌曲专辑的 bitmap 图。
(4) app widget 接收广播,并实现更新。
@Override
public void onReceive(Context context, Intent intent) {
if("update_appwidget".equals(intent.getAction())){
//接收数据
Intent _intent = intent;
Bundle b =_intent.getExtras();
Bitmap bmp = (Bitmap) b.getParcelable("bitmap");
String[] str = b.getStringArray("data");
//更新 appwidget
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.appwidget);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
remoteViews.setTextViewText(R.id.appwidget_text_name, str[0]);
remoteViews.setTextViewText(R.id.appwidget_text_singer, str[1]);
remoteViews.setImageViewBitmap(R.id.appwidget_image , bmp);
appWidgetManager.updateAppWidget(new ComponentName(context, MyAppWidget.class), remoteViews);
}
super.onReceive(context, intent);
}
(5) 切记,要在 AndroidMainIfest.xml 中注册 intent-filter
注册在 app widget 的 revice 里面。
至此,音乐播放器 appwidget 功能已全部实现。