这时一个可以播放网络音乐的小小播放器,主要拿来理解Boradcast和Service的。
下面只贴主要代码。

MusicPlayService.java
package com.solo.test.e2ecloud.service;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.IBinder;
import android.util.Log;
public class MusicPlayService extends Service {
/* 用于执行播放,暂停,停止命令 */
public static final int CMD_PLAY = 0;
public static final int CMD_PAUSE = 1;
public static final int CMD_STOP = 2;
/* 用于标识当前播放状态 */
private int status;
public static final int STATUS_PLAYING = 0;
public static final int STATUS_PAUSED = 1;
public static final int STATUS_STOPPED = 2;
/* 用于发出Broadcast*/
public static final String MUSIC_CONTROL = "TinyPlayer.ACTION_CONTROL";
public static final String UPDATE_STATUS = "TinyPlayer.ACTION_UPDATE";
MediaPlayer mPlayer;
/* 媒体资源重播已经完成的时候回调 */
OnCompletionListener completed;
/*内部类CommandReceiver*/
private CommandReceiver doCommand;
private String TAG = "MusicPlayService";
/* 用于发出更新用户界面状态的Broadcast */
private void updateUi() {
Log.i(TAG , "Update ui now and send broadcast.Any body here?");
/*
* 发出带有UPDATE_STATUS这个意图的广播,
* 若有intent-filter为TinyPlayer.ACTION_UPDATE的广播接收者,将会收到这个广播
*/
Intent intent = new Intent(UPDATE_STATUS);
intent.putExtra("status", status);
sendBroadcast(intent);
}
/* 内部类,用于接收Broadcast发送的命令,并根据这些命令执行相应的播放,暂停,停止操作。 */
class CommandReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG , "wait,i got a broadcast");
// TODO Auto-generated method stub
switch (intent.getIntExtra("cmd", –1)) {
case CMD_PLAY:
Uri uriMedia = intent.getData();
if(uriMedia!=null){
/* 停止当前播放的音乐 并播放传过来的Uri
*如果不再需要MediaPlayer对象,要释放,不然过多的对象会出抛异常
*/
mPlayer.release();
mPlayer = MediaPlayer.create(context, uriMedia);
/* 设置音乐播放完毕后的监听器*/
mPlayer.setOnCompletionListener(completed);
try{
mPlayer.start();
}catch(Exception ex){
ex.printStackTrace();
}
}else{
mPlayer.start();
}
status = STATUS_PLAYING;
break;
case CMD_PAUSE:
mPlayer.pause();
status = STATUS_PAUSED;
break;
case CMD_STOP:
mPlayer.stop();
status=STATUS_STOPPED;
break;
default:
Log.i(TAG , "command can't find?");
break;
}
/*更新UI*/
updateUi();
}
}
@Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
updateUi();
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
unregisterReceiver(doCommand);
}
@Override
public void onCreate(){
Log.i(TAG , "Let me do something in onCreate()");
/* 主要对CommandReceiver进行动态注册*/
mPlayer = new MediaPlayer();
/*初始状态为停止*/
status = STATUS_STOPPED;
doCommand = new CommandReceiver();
/*
* 构造一个IntentFilter
* action:"TinyPlayer.ACTION_CONTROL"
* scheme:"http"
* 相当于AndroidManifest.xml文件里注册
*/
IntentFilter filter1= new IntentFilter();
filter1.addAction(MUSIC_CONTROL);
filter1.addDataScheme("http");
registerReceiver(doCommand,filter1);
IntentFilter filter2 = new IntentFilter();
filter2.addAction(MUSIC_CONTROL);
registerReceiver(doCommand,filter2);
completed = new OnCompletionListener(){
@Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
Log.i(TAG, "source is completion?");
mp.stop();;
status = STATUS_STOPPED;
updateUi();
}
};
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
TinyPlayer.java
package com.solo.test.e2ecloud.player;
import com.solo.test.e2ecloud.dialer.R;
import com.solo.test.e2ecloud.player.TinyPlayer.UpdateReceiver;
import com.solo.test.e2ecloud.service.MusicPlayService;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
public class TinyPlayer extends Activity {
private String TAG = "TinyPlayer";
private final int DIALOG_ABOUT = 1;
/* 用于表示当前状态 */
private int status;
private ImageButton btnStart;
private ImageButton btnStop;
private Uri uriNowPlaying;
private OnClickListener listenter;
// 内部类声明
private UpdateReceiver doUpdate;
/* 内部类 */
public class UpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.i(TAG , "wait,i got a broadcast");
/* 获取状态 */
status = intent.getIntExtra("status", –1);
switch (status) {
case MusicPlayService.STATUS_PLAYING:
btnStart.setImageResource(R.drawable.playselector);
break;
case MusicPlayService.STATUS_PAUSED:
case MusicPlayService.STATUS_STOPPED:
// 没实现
break;
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.setContentView(R.layout.player);
/* find view by id */
btnStart = (ImageButton) this.findViewById(R.id.playorpause);
btnStop = (ImageButton) this.findViewById(R.id.stop);
/* 设置当前播放的Uri */
uriNowPlaying = Uri
.parse("http://zhangmenshiting.baidu.com/service/224822a2eb0cd713311d020519eb3be9.mp3?xcode=39a942ceb719dbdd0218fa1269adcc912a");
/* 定义按钮点击事件的监听器 */
listenter = new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
/* 如果没有选定正在播放的音乐,直接忽略操作 */
if (uriNowPlaying == null) {
Log.i(TAG, "?? you don't have any music");
return;
}
int cmd = 0;
Intent i = new Intent(MusicPlayService.MUSIC_CONTROL);
switch (v.getId()) {
case R.id.playorpause:
if (status == MusicPlayService.STATUS_PLAYING) {
/* 如果当前为播放,则暂停 */
cmd = MusicPlayService.CMD_PAUSE;
Log.i(TAG, "now playing,so pause");
} else if (status == MusicPlayService.STATUS_STOPPED) {
/* 如果停止,装载Uri并播放 */
i.setData(uriNowPlaying);
cmd = MusicPlayService.CMD_PLAY;
Log.i(TAG, "now stop,xu,the music will start");
} else {
/* 如果是暂停,就继续播放 */
cmd = MusicPlayService.CMD_PLAY;
Log.i(TAG, "now pause,don't worry,i go on immediately");
}
break;
case R.id.stop:
cmd = MusicPlayService.CMD_STOP;
Log.i(TAG, "uh,you listen to much,take a break");
break;
default:
break;
}
Log.i(TAG, "wait,i going to send the broadcast with cmmand");
i.putExtra("cmd", cmd);
sendBroadcast(i);
}
};
/* 注册事件监听 */
btnStart.setOnClickListener(listenter);
btnStop.setOnClickListener(listenter);
/* 接收带有意图为TinyPlayer.ACTION_UPDATE的广播*/
doUpdate = new UpdateReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(MusicPlayService.UPDATE_STATUS);
registerReceiver(doUpdate, filter);
Log.i(TAG, "start service is important,let me do it");
startService(new Intent(this, MusicPlayService.class));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
Log.i(TAG, "oh,no,you click me on option item");
switch (item.getItemId()) {
case Menu.FIRST:
this.showDialog(DIALOG_ABOUT);
break;
default:
break;
}
return false;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
Log.i(TAG, "create the option menu");
menu.add(0, Menu.FIRST, 0, R.string.about).setIcon(
android.R.drawable.ic_menu_info_details);
return true;
}
@Override
protected Dialog onCreateDialog(int id) {
// TODO Auto-generated method stub
Log.i(TAG, "yes,you are right,i override the dialog");
switch (id) {
case DIALOG_ABOUT:
return new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_info)
.setTitle(R.string.about).setMessage(R.string.about_info)
.setPositiveButton(R.string.confirm, null).create();
default:
return null;
}
}
}
AndroidManifest.xml
<!– 为了使service能够在Activity退出后依然运行,需process=remote,意思为远端进程,独立进程,生命周期与Acticity无关 –> <service android:name="com.solo.test.e2ecloud.service.MusicPlayService" android:process=":remote"></service> </application>
<!– 4 为了访问网络资源,要加入这个权限 –>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>