Widget在手机应用上可谓是个宠儿,基本上好的手机平台不仅应用程序做的好,WIDGET也做的非常好。今天我就把早前做的一个山寨 widget播放器,和大家一起分享分享。为什么说他山寨呢?因为我把它也放到应用程序列表里,只是把widget放在手机主页的功能拷了过来。实例中的 图片是在网络找的,歌曲随便添加(声明:音乐名称使用的是英文,中文会出问题,具体原因不知,请有知道大侠帮忙指点指点)好了闲话就不多说了,开始我们的实例:
首先我们要向SD卡中添加音频文件。步骤如下:启动模拟器,在Eclipses上选择DDMS窗口,选择File Explorer标签。如下图:
向左、向右箭头分别是拷出、拷进制定位置。
然后我们就开始新建一个项目WidgetMusicPlay
编写WidegetMusicPlay.java,代码如下:
package com.croft.demo;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ListView;
public class WidgetMusicPlay extends ListActivity implements OnClickListener {
/** 几个操作按钮 */
private ImageButton LastImageButton = null;
private ImageButton StopImageButton = null;
private ImageButton StartImageButton = null;
private ImageButton PauseImageButton = null;
private ImageButton NextImageButton = null;
private Intent musicIntent;
/** 播放列表 */
private List<String> mMusicList = new ArrayList<String>();
/** 音乐的路径 */
private static final String MUSIC_PATH = new String("/sdcard/");
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/** 更新显示播放列表 */
musicList();
// 新创建一个Intent,把启动的服务加到Intent中
musicIntent = new Intent("com.croft.demo.START_AUDIO_SERVICE");
LastImageButton = (ImageButton) findViewById(R.id.LastImageButton);
StopImageButton = (ImageButton) findViewById(R.id.StopImageButton);
StartImageButton = (ImageButton) findViewById(R.id.StartImageButton);
PauseImageButton = (ImageButton) findViewById(R.id.PauseImageButton);
NextImageButton = (ImageButton) findViewById(R.id.NextImageButton);
// 给各个按钮添加事件监听器,监听器由本类来实现OnClickListener接口
myButtonSetListener();
}
private void myButtonSetListener() {
LastImageButton.setOnClickListener(this);
StopImageButton.setOnClickListener(this);
StartImageButton.setOnClickListener(this);
PauseImageButton.setOnClickListener(this);
NextImageButton.setOnClickListener(this);
}
@Override
public void onClick(View button) {
// TODO Auto-generated method stub
// 根据button.getId()获取View的ID来判断事件是由那个按钮来发出的,然后进行相应的事件处理
switch (button.getId()) {
case R.id.StartImageButton: {
musicIntent.setFlags(R.id.StartImageButton);
// 启动音乐播放服务
this.startService(musicIntent);
}
break;
case R.id.StopImageButton: {
// 停止音乐播放服务
this.stopService(musicIntent);
}
break;
case R.id.LastImageButton: {
musicIntent.setFlags(R.id.LastImageButton);
// 启动音乐播放服务
this.startService(musicIntent);
}
break;
case R.id.NextImageButton: {
musicIntent.setFlags(R.id.NextImageButton);
// 启动音乐播放服务
this.startService(musicIntent);
}
break;
case R.id.PauseImageButton: {
musicIntent.setFlags(R.id.PauseImageButton);
// 启动音乐播放服务
this.startService(musicIntent);
}
break;
default:
break;
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// 停止音乐播放服务
this.stopService(musicIntent);
this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
/* 当我们点击列表时,播放被点击的音乐 */
protected void onListItemClick(ListView l, View v, int position, long id) {
musicIntent.setFlags(position);
this.startService(musicIntent);
}
/** 播放列表 */
public void musicList() {
// 取得指定位置的文件设置显示到播放列表
File home = new File(MUSIC_PATH);
if (home.listFiles(new MusicFilter()).length > 0) {
for (File file : home.listFiles(new MusicFilter())) {
mMusicList.add(file.getName());
}
ArrayAdapter<String> musicList = new ArrayAdapter<String>(
WidgetMusicPlay.this, R.layout.musicitme, mMusicList);
setListAdapter(musicList);
}
}
/** 过滤文件类型 */
class MusicFilter implements FilenameFilter {
public boolean accept(File dir, String name) {
// 这里还可以设置其他格式的音乐文件
return (name.endsWith(".mp3"));
}
}
}
写完了Activity后我们还要些个最关键的Service,播放器的播放功能都在这里面。
MusicService.java
package com.croft.demo;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.IBinder;
public class MusicService extends Service {
// 声明一个MediaPlayer实例对象
public MediaPlayer myMusicPlayer = new MediaPlayer();
/** 当前播放歌曲的索引 */
private int currentListItme = 0;
/** 播放列表 */
private List<String> mMusicList = new ArrayList<String>();
/** 音乐的路径 */
private static final String MUSIC_PATH = new String("/sdcard/");
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
// 服务启动方法
@Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
// 取得指定位置的文件设置显示到播放列表
musicList();
int flag = intent.getFlags();
switch (flag) {
case R.id.StartImageButton: {
playMusic(MUSIC_PATH + mMusicList.get(currentListItme));
}
break;
case R.id.LastImageButton: {
FrontMusic();
}
break;
case R.id.NextImageButton: {
nextMusic();
}
break;
case R.id.PauseImageButton: {
PauseMusic();
}
break;
default:
playMusic(MUSIC_PATH + mMusicList.get(flag));
break;
}
}
// 服务销毁方法
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
// 停止音乐播放
myMusicPlayer.stop();
myMusicPlayer.release();
}
/** 下一首 */
private void nextMusic() {
if (++currentListItme >= mMusicList.size()) {
currentListItme = 0;
playMusic(MUSIC_PATH + mMusicList.get(currentListItme));
} else {
playMusic(MUSIC_PATH + mMusicList.get(currentListItme));
}
}
/** 上一首 */
private void FrontMusic() {
if (--currentListItme < 0) {
currentListItme = mMusicList.size() - 1;
playMusic(MUSIC_PATH + mMusicList.get(currentListItme));
} else {
playMusic(MUSIC_PATH + mMusicList.get(currentListItme));
}
}
private void PauseMusic() {
if (myMusicPlayer.isPlaying()) {
/** 暂停 */
myMusicPlayer.pause();
} else {
/** 开始播放 */
myMusicPlayer.start();
}
}
public void playMusic(String path) {
try {
/** 重置MediaPlayer */
myMusicPlayer.reset();
/** 设置要播放的文件的路径 */
myMusicPlayer.setDataSource(path);
// 准备播放器,进行回放
myMusicPlayer.prepare();
// 启动MediaPlayer
myMusicPlayer.start();
myMusicPlayer.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
// 播放完成一首之后进行下一首
nextMusic();
}
});
} catch (IOException e) {
}
}
/** 播放列表 */
public void musicList() {
// 取得指定位置的文件设置显示到播放列表
File home = new File(MUSIC_PATH);
if (home.listFiles(new MusicFilter()).length > 0) {
for (File file : home.listFiles(new MusicFilter())) {
mMusicList.add(file.getName());
}
}
}
/** 过滤文件类型 */
class MusicFilter implements FilenameFilter {
public boolean accept(File dir, String name) {
// 这里还可以设置其他格式的音乐文件
return (name.endsWith(".mp3"));
}
}
}
然后我们要给应用程序添加成widget的效果,在AndroidManifest.xml文件里面修改
<application android:icon="@drawable/icon" ;android:label="@string/app_name">
<activity android:name=".WidgetMusicPlay" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="MusicService">
<intent-filter>
<action android:name="com.croft.demo.START_AUDIO_SERVICE"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</service>
<receiver android:name="MusicAppWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>
<action android:name="com.croft.demo.START_AUDIO_CLICK"></action>
<action android:name="com.croft.demo.STOP_AUDIO_CLICK"></action>
<action android:name="com.croft.demo.PAUSE_AUDIO_CLICK"></action>
<action android:name="com.croft.demo.LAST_AUDIO_CLICK"></action>
<action android:name="com.croft.demo.NEXT_AUDIO_CLICK"></action>
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/example_appwidget_info">
</meta-data>
</receiver>
</application>
其中<intent-filter>中的内容我们等下要在编写的MusicAppWidgetProvider文件中用到,实现widget播放功能
MusicAppWidgetProvider.java
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
super.onReceive(context, intent);
if(intent.getAction().equals("com.croft.demo.START_AUDIO_CLICK")) {
//Toast.makeText(context, "It works", Toast.LENGTH_SHORT).show();
musicIntent=new Intent("com.croft.demo.START_AUDIO_SERVICE");
musicIntent.setFlags(R.id.StartImageButton);
context.startService(musicIntent);
}
if(intent.getAction().equals("com.croft.demo.STOP_AUDIO_CLICK")) {
// Toast.makeText(context, "It works", Toast.LENGTH_SHORT).show();
musicIntent=new Intent("com.croft.demo.START_AUDIO_SERVICE");
context.stopService(musicIntent);
}
if(intent.getAction().equals("com.croft.demo.LAST_AUDIO_CLICK")) {
//Toast.makeText(context, "It works", Toast.LENGTH_SHORT).show();
musicIntent=new Intent("com.croft.demo.START_AUDIO_SERVICE");
musicIntent.setFlags(R.id.LastImageButton);
context.startService(musicIntent);
}
if(intent.getAction().equals("com.croft.demo.NEXT_AUDIO_CLICK")) {
//Toast.makeText(context, "It works", Toast.LENGTH_SHORT).show();
musicIntent=new Intent("com.croft.demo.START_AUDIO_SERVICE");
musicIntent.setFlags(R.id.NextImageButton);
context.startService(musicIntent);
}
if(intent.getAction().equals("com.croft.demo.PAUSE_AUDIO_CLICK")) {
//Toast.makeText(context, "It works", Toast.LENGTH_SHORT).show();
musicIntent=new Intent("com.croft.demo.START_AUDIO_SERVICE");
musicIntent.setFlags(R.id.PauseImageButton);
context.startService(musicIntent);
}
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
// 修改。。
super.onUpdate(context, appWidgetManager, appWidgetIds);
//开始播放
musicIntent = new Intent("com.croft.demo.START_AUDIO_CLICK");
//musicIntent.setComponent(serviceName);
pendingIntent = PendingIntent.getBroadcast(context, 0,
musicIntent, 0);
// 为App Widget 取得布局并且拴一个on-click 监听器到该 button 上
views = new RemoteViews(context.getPackageName(),
R.layout.mywidgetlayout);
views.setOnClickPendingIntent(R.id.StartImageButton, pendingIntent);
// 告诉 AppWidgetManager 在当前App Widget上 执行一次更新
appWidgetManager.updateAppWidget(appWidgetIds, views);
//停止播放
musicIntent = new Intent("com.croft.demo.STOP_AUDIO_CLICK");
//musicIntent.setComponent(serviceName);
pendingIntent = PendingIntent.getBroadcast(context, 0,
musicIntent, 0);
// 为App Widget 取得布局并且拴一个on-click 监听器到该 button 上
views = new RemoteViews(context.getPackageName(),
R.layout.mywidgetlayout);
views.setOnClickPendingIntent(R.id.StopImageButton, pendingIntent);
// 告诉 AppWidgetManager 在当前App Widget上 执行一次更新
appWidgetManager.updateAppWidget(appWidgetIds, views);
//上一首
musicIntent = new Intent("com.croft.demo.LAST_AUDIO_CLICK");
//musicIntent.setComponent(serviceName);
pendingIntent = PendingIntent.getBroadcast(context, 0,
musicIntent, 0);
// 为App Widget 取得布局并且拴一个on-click 监听器到该 button 上
views = new RemoteViews(context.getPackageName(),
R.layout.mywidgetlayout);
views.setOnClickPendingIntent(R.id.LastImageButton, pendingIntent);
// 告诉 AppWidgetManager 在当前App Widget上 执行一次更新
appWidgetManager.updateAppWidget(appWidgetIds, views);
//下一首
musicIntent = new Intent("com.croft.demo.NEXT_AUDIO_CLICK");
//musicIntent.setComponent(serviceName);
pendingIntent = PendingIntent.getBroadcast(context, 0,
musicIntent, 0);
// 为App Widget 取得布局并且拴一个on-click 监听器到该 button 上
views = new RemoteViews(context.getPackageName(),
R.layout.mywidgetlayout);
views.setOnClickPendingIntent(R.id.NextImageButton, pendingIntent);
// 告诉 AppWidgetManager 在当前App Widget上 执行一次更新
appWidgetManager.updateAppWidget(appWidgetIds, views);
//暂停播放
musicIntent = new Intent("com.croft.demo.PAUSE_AUDIO_CLICK");
//musicIntent.setComponent(serviceName);
pendingIntent = PendingIntent.getBroadcast(context, 0,
musicIntent, 0);
// 为App Widget 取得布局并且拴一个on-click 监听器到该 button 上
views = new RemoteViews(context.getPackageName(),
R.layout.mywidgetlayout);
views.setOnClickPendingIntent(R.id.PauseImageButton, pendingIntent);
// 告诉 AppWidgetManager 在当前App Widget上 执行一次更新
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
程序运行的效果图: