程序实现如下功能:当点击播放按钮,按钮进行播放音乐,同时按钮背景图片切换成暂停按钮,当点击暂停按钮时,音乐暂停播放,同时按钮背景图片切换成播放按钮,点击重置按钮,音乐停止播放。
效果图如下:
首先简述下编写思路:
程序通过service与广播接收者实现。在主功能代码中发送广播,有一个命令广播接收者,用来接收命令,一个更新UI的广播接收者,用来接收命令广播发送过来的状态,根据状态更新UI。
给出代码:
布局文件给出一个进度条,一个TextView控件,用来标识播放进度,一个播放暂停按钮,一个重置按钮,成垂直布局。
在主功能代码中获取按钮控件,为按钮控件设置事件监听,当点击播放暂停按钮时,需要判断当前的状态,如果为停止状态,则需要将路径,播放命令发送出去,如果为暂停状态,发送播放状态即可,在命令广播接收类中通过判断命令来对应相应的操作。同时动态注册命令接收广播,启动服务。
在命令广播接收类中,判断命令,使用path是否为空来判断是暂停后播放,还是停止状态后播放。在这个类中主要实现播放音乐,同时更改当前状态发送至UI更新广播类中,
在这个广播接收类中主要实现UI的更新。
效果图如下:
首先简述下编写思路:
程序通过service与广播接收者实现。在主功能代码中发送广播,有一个命令广播接收者,用来接收命令,一个更新UI的广播接收者,用来接收命令广播发送过来的状态,根据状态更新UI。
给出代码:
首先是布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ProgressBar
android:id="@+id/pb"
android:layout_marginTop="3dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@android:style/Widget.ProgressBar.Horizontal"
/>
<TextView
android:id="@+id/tv"
android:layout_marginTop="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="0:00/0:00"
android:textSize="12sp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="horizontal"
>
<ImageButton
android:id="@+id/pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/pause"
/>
<ImageButton
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/stop"
android:layout_marginLeft="5dp"
/>
</LinearLayout>
</LinearLayout>
布局文件给出一个进度条,一个TextView控件,用来标识播放进度,一个播放暂停按钮,一个重置按钮,成垂直布局。
接下来实现主功能代码:
package com.example.sample5_11tdw;
import android.support.v7.app.ActionBarActivity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageButton;
public class MainActivity extends ActionBarActivity {
private ImageButton pause;//暂停
private ImageButton stop;//停止
private String path = "/sdcard/zdan.mp3";
private UpateUIReceiver uuRece;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InitViews();
}
private void InitViews() {
pause = (ImageButton) findViewById(R.id.pause);
stop = (ImageButton) findViewById(R.id.stop);
uuRece = new UpateUIReceiver(this);
//当前状态为暂停,点击后进行播放
pause.setOnClickListener(new View.OnClickListener() {//暂停事件监听
@Override
public void onClick(View v) {
if(uuRece.status == Constanly.STATUS_PLAY){//如果当前状态为播放
Intent intent = new Intent(Constanly.MUSIC_CONTROL);
//发送暂停命令
intent.putExtra("cmd", Constanly.COMMAND_PAUSE);
MainActivity.this.sendBroadcast(intent);
}else if(uuRece.status == Constanly.STATUS_STOP)
{
//当前状态为暂停
Intent intent = new Intent(Constanly.MUSIC_CONTROL);
intent.putExtra("path", path);
intent.putExtra("cmd", Constanly.COMMAND_PLAY);
MainActivity.this.sendBroadcast(intent);
}else if(uuRece.status == Constanly.STATUS_PAUSE)
{//若当前状态为暂停,则继续播放
Intent intent = new Intent(Constanly.MUSIC_CONTROL);
intent.putExtra("cmd", Constanly.COMMAND_PLAY);
MainActivity.this.sendBroadcast(intent);
}
}
});
stop.setOnClickListener(new View.OnClickListener() {//停止事件监听,将播放的路径发送过去
@Override
public void onClick(View v) {
Intent intent = new Intent(Constanly.MUSIC_CONTROL);
intent.putExtra("cmd", Constanly.COMMADN_STOP);
MainActivity.this.sendBroadcast(intent);
}
});
//动态注册更新UI的广播事件
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Constanly.UPDATE_UI);
registerReceiver(uuRece, intentFilter);
this.startService(new Intent(MainActivity.this,MyMusicService.class));
}
@SuppressWarnings("deprecation")
@Override
protected void onStart() {
super.onStart();
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this,MainActivity.class);
//将Intent封装为PendingIntent
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
Notification notification = new Notification();
notification.icon = R.drawable.notilogo;
notification.vibrate = new long[]{200,300};//200毫秒后震动300毫秒
notification.setLatestEventInfo(this, "音乐播放器正在运行中", "单击查看", pi);
nm.notify(0,notification);
}
@Override
protected void onDestroy() {
super.onDestroy();
this.unregisterReceiver(uuRece);
}
}
在主功能代码中获取按钮控件,为按钮控件设置事件监听,当点击播放暂停按钮时,需要判断当前的状态,如果为停止状态,则需要将路径,播放命令发送出去,如果为暂停状态,发送播放状态即可,在命令广播接收类中通过判断命令来对应相应的操作。同时动态注册命令接收广播,启动服务。
给出命令广播接收类:
package com.example.sample5_11tdw;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Looper;
import android.view.LayoutInflater;
import android.widget.ImageButton;
public class CommandReceiver extends BroadcastReceiver{
public MediaPlayer mp;
public int status;
@Override
public void onReceive(final Context context, Intent intent) {
switch (intent.getIntExtra("cmd", -1)) {
case Constanly.COMMAND_PLAY:
String path = intent.getStringExtra("path");
if(path != null){//path不为空,说明是停止后重新播放
//说明之前已经有MediaPlayer对象了,要进行释放
if(mp != null){
mp.release();
}
mp=new MediaPlayer();
try {
//为音乐播放器添加完成监听
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
//歌曲播放完毕
@Override
public void onCompletion(MediaPlayer mp) {
mp.stop();
status = Constanly.STATUS_STOP;
updateUI(context);
}
});
mp.setDataSource(path);
//通过new MediaPlayer()一定要先进行prepare()
mp.prepare();
//开始播放
mp.start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//发送消息改变进度条的进度
new Thread(){
@Override
public void run() {
Looper:while(true){
//如果当前状态为停止状态
if(status == Constanly.STATUS_STOP){
break Looper;
}
int duration = 0;//总时间
int current = 0;//当前时间
//如果状态为暂停或者播放
if(status == Constanly.STATUS_PAUSE || status == Constanly.STATUS_PLAY){
duration = mp.getDuration();
current = mp.getCurrentPosition();
Intent intent = new Intent(Constanly.UPDATE_UI);
intent.putExtra("status", Constanly.PROGRESS_GO);
intent.putExtra("duration", duration);
intent.putExtra("current", current);
//广播Intent
context.sendBroadcast(intent);
}
}
};
}.start();
}else
{
//如果是暂停后播放,直接继续播放即可
mp.start();
}
status = Constanly.STATUS_PLAY;
break;
case Constanly.COMMAND_PAUSE:
status = Constanly.STATUS_PAUSE;
mp.pause();
break;
case Constanly.COMMADN_STOP:
status = Constanly.STATUS_STOP;
mp.stop();
break;
}
updateUI(context);
}
protected void updateUI(Context context) {
Intent intent = new Intent(Constanly.UPDATE_UI);
intent.putExtra("status", status);
context.sendBroadcast(intent);
}
}
在命令广播接收类中,判断命令,使用path是否为空来判断是暂停后播放,还是停止状态后播放。在这个类中主要实现播放音乐,同时更改当前状态发送至UI更新广播类中,
给出UI广播接收类:
package com.example.sample5_11tdw;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;
public class UpateUIReceiver extends BroadcastReceiver{
private Activity ac;
public int status;
public UpateUIReceiver(Activity ac) {
this.ac = ac;
}
@Override
public void onReceive(Context context, Intent intent) {
ImageButton pauseButton = (ImageButton) ac.findViewById(R.id.pause);
ProgressBar pb = (ProgressBar) ac.findViewById(R.id.pb);
int tempStatus = intent.getIntExtra("status", -1);
switch (tempStatus) {
case Constanly.STATUS_PLAY:
pauseButton.setImageResource(R.drawable.pause);
status = tempStatus;
break;
case Constanly.STATUS_PAUSE:
pauseButton.setImageResource(R.drawable.play);
status = tempStatus;
break;
case Constanly.STATUS_STOP:
pb.setProgress(0);
pauseButton.setImageResource(R.drawable.play);
status = tempStatus;
break;
case Constanly.PROGRESS_GO:
int duration = intent.getIntExtra("duration", 0);
int current = intent.getIntExtra("current", 0);
pb.setMax(duration);
pb.setProgress(current);
TextView tv = (TextView) ac.findViewById(R.id.tv);
tv.setText(convertToMinute(current)+"/"+convertToMinute(duration));
break;
}
}
private String convertToMinute(int value) {//得到的是毫秒值,返回格式0:00
int second = value / 1000;
int minute = second / 60;
second = second % 60;
String minStr = String.valueOf(minute);
String secStr = String.valueOf(second);
return minStr+":"+(second>9?second:"0"+second);
}
}
在这个广播接收类中主要实现UI的更新。
一个常量类:
package com.example.sample5_11tdw;
public class Constanly {//常量类
//播放命令
public final static int COMMAND_PLAY = 0;
//暂停命令
public final static int COMMAND_PAUSE = 1;
//停止命令
public final static int COMMADN_STOP = 2;
//播放状态
public final static int STATUS_PLAY = 3;
//暂停状态
public final static int STATUS_PAUSE = 4;
//停止状态
public final static int STATUS_STOP = 5;
//状态更新常量
public final static int PROGRESS_GO = 6;
//更新界面
public final static String UPDATE_UI = "UPDATE_UI";
//音乐控制
public final static String MUSIC_CONTROL = "MUSIC_CONTROL";
}
给出service服务类:
package com.bn.chap5.no;
import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.os.IBinder;
//后台播放的Service类
public class MyMusicPlayerService extends Service {
CommandReceiver cr;//命令Intent接收者对象引用
@Override
public IBinder onBind(Intent intent)
{//因为本例用不到Bind功能,因此直接返回null
return null;
}
@Override
public void onCreate()
{
super.onCreate();
//创建命令Intent接收者对象
cr=new CommandReceiver();
//创建媒体播放器对象
cr.mp=new MediaPlayer();
//初始状态为停止状态
cr.status=Constant.STATUS_STOP;
//动态注册接收播放、暂停、停止命令Intent的CommandReceiver
IntentFilter filter=new IntentFilter();
filter.addAction(Constant.MUSIC_CONTROL);
this.registerReceiver(cr, filter);
}
@Override
public void onDestroy()
{
super.onDestroy();
//取消注册接收播放、暂停、停止命令Intent的CommandReceiver
this.unregisterReceiver(cr);
//释放播放器对象
cr.mp.release();
}
@Override
public void onStart(Intent intent, int id)
{
//更新界面状态
cr.updateUI(this.getApplicationContext());
}
}
记得在清单文件需要注册service类:
<service android:name=".MyMusicService" android:process=":remote"></service>
代码链接: