Android开发之基于Service的音乐播放器

            这是一个基于Service组件的音乐播放器,程序的音乐将会由后台的Service组件负责播放,当后台的播放状态改变时,程序将会通过发送广播通知前台Activity更新界面;当用户单击前台Activity的界面按钮或拖动进度条时,系统通过发送广播通知后台Service来改变播放状态和播放指定音乐。

程序运行效果图:

基于Service的音乐播放器

Android音乐播放器       音乐播放器项目结构

程序代码:

程序界面类(MusicBox.java):

package com.jph.musicbox;import com.jph.util.ConstUtil;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
/*** Describe:
*
基于Service的音乐播发器*
本应用主要实现了:*
1.通过前台Activity发出播放相关的控制信息,以广播的形式*
传递给后台的Service,后台的Service负责音乐的播放。*
并负责接收后台的广播来更新播放界面的歌曲名、歌手名。*
2.通过进度条来显示当前播放的位置,当用户拖动进度条时*
通过OnSeekBarChangeListener事件来控制*
后台的mediaPlayer播放指定位置的音乐。*
@author jph*
Date:2014.08.07* */ public class MusicBox extends Activity { ImageButton btnPlayOrPause,btnPre,btnNext; //进度条static SeekBar skbMusic;// 获取界面中显示歌曲标题、作者文本框TextView title, author; String[] titleStrs = new String[] { "涛声依旧", "油菜花", "You Are The One" };String[] authorStrs = new String[] { "毛宁", "成龙", "未知艺术家" };//是否正在播放boolean isPlaying=false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);skbMusic=(SeekBar)findViewById(R.id.skbMusic);skbMusic.setOnSeekBarChangeListener(sChangeListener);btnNext=(ImageButton)findViewById(R.id.btnNext);btnPlayOrPause=(ImageButton)findViewById(R.id.btnPlayOrPause);btnPre=(ImageButton)findViewById(R.id.btnPre);btnNext.setOnClickListener(listener);btnPlayOrPause.setOnClickListener(listener);btnPre.setOnClickListener(listener);title=(TextView)findViewById(R.id.title);author=(TextView)findViewById(R.id.author);title.setText(titleStrs[0]);author.setText(authorStrs[0]); //注册接收器MusicBoxReceiver mReceiver=new MusicBoxReceiver();IntentFilter filter=new IntentFilter();filter.addAction(ConstUtil.MUSICBOX_ACTION);registerReceiver(mReceiver, filter);//启动后台ServiceIntent intent=new Intent(this, MusicService.class);startService(intent);}OnClickListener listener=new OnClickListener() { @Overridepublic void onClick(View v) {// TODO Auto-generated method stubswitch (v.getId()) {case R.id.btnNext://下一首btnPlayOrPause.setBackgroundResource(R.drawable.state_pasue);sendBroadcastToService(ConstUtil.STATE_NEXT); isPlaying=true;break;case R.id.btnPlayOrPause://播放或暂停if (!isPlaying) {btnPlayOrPause.setBackgroundResource(R.drawable.state_pasue);sendBroadcastToService(ConstUtil.STATE_PLAY);isPlaying=true;}else {btnPlayOrPause.setBackgroundResource(R.drawable.state_play);sendBroadcastToService(ConstUtil.STATE_PAUSE);isPlaying=false;}break;case R.id.btnPre://上一首btnPlayOrPause.setBackgroundResource(R.drawable.state_pasue);sendBroadcastToService(ConstUtil.STATE_PREVIOUS);isPlaying=true;break;default:break;} }};/*** SeekBar进度改变事件*/OnSeekBarChangeListener sChangeListener=new OnSeekBarChangeListener() { @Overridepublic void onStopTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stub//当拖动停止后,控制mediaPlayer播放指定位置的音乐MusicService.mediaPlayer.seekTo(seekBar.getProgress());MusicService.isChanging=false; }@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stubMusicService.isChanging=true;}@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {// TODO Auto-generated method stub}};@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present. menu.add(Menu.NONE, ConstUtil.MENU_ABOUT, Menu.NONE, "关于");menu.add(Menu.NONE, ConstUtil.MENU_EXIT, Menu.NONE, "退出");return true;}/***向后台Service发送控制广播*@param state int state 控制状态码* */protected void sendBroadcastToService(int state) {// TODO Auto-generated method stubIntent intent=new Intent();intent.setAction(ConstUtil.MUSICSERVICE_ACTION);intent.putExtra("control", state);//向后台Service发送播放控制的广播sendBroadcast(intent);}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// TODO Auto-generated method stub switch (item.getItemId()) {case ConstUtil.MENU_ABOUT:LayoutInflater inflater=LayoutInflater.from(this);LinearLayout layout=(LinearLayout) inflater.inflate(R.layout.about, null);AlertDialog dialog=new AlertDialog.Builder(this).create();dialog.setTitle("关于");dialog.setIcon(R.drawable.ic_launcher);dialog.setView(layout);dialog.show();break;case ConstUtil.MENU_EXIT:sendBroadcastToService(ConstUtil.STATE_STOP);this.finish();break;default:break;}return true;}//创建一个广播接收器用于接收后台Service发出的广播 class MusicBoxReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stub// 获取Intent中的current消息,current代表当前正在播放的歌曲int current = intent.getIntExtra("current", -1);title.setText(titleStrs[current]);//更新音乐标题author.setText(authorStrs[current]);//更新音乐作者}} }
负责音乐播放的后台Service类:

MusicService.java

package com.jph.musicbox;import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;import com.jph.util.ConstUtil;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.IBinder;
/*** Describe:
*
负责音乐播放的后台Service*
1.通过接收来自前台的控制播放信息的广播来播放指定音乐*
2.加载assets目录下的音乐*
3.为mediaPlayer的完成事件创建监听器当当前音乐播放*
完成后自动播放下一首音乐*
4.为每一首正在播放的音乐创建一个定时器,用于检测播放进度*
并更新进度条 *
@author jph*
Date:2014.08.07* */ public class MusicService extends Service {Timer mTimer;TimerTask mTimerTask;static boolean isChanging=false;//互斥变量,防止定时器与SeekBar拖动时进度冲突//创建一个媒体播放器的对象static MediaPlayer mediaPlayer;//创建一个Asset管理器的的对象AssetManager assetManager;//存放音乐名的数组String[]musics=new String[]{"taoshengyijiu-maoning.mp3", "youcaihua-chenglong.mp3","You Are The One.mp3" };//当前的播放的音乐int current=0;//当前播放状态int state=ConstUtil.STATE_NON;//记录Timer运行状态boolean isTimerRunning=false;@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate(); //注册接收器MusicSercieReceiver receiver=new MusicSercieReceiver();IntentFilter filter=new IntentFilter();filter.addAction(ConstUtil.MUSICSERVICE_ACTION);registerReceiver(receiver, filter);mediaPlayer=new MediaPlayer();assetManager=getAssets();//为mediaPlayer的完成事件创建监听器mediaPlayer.setOnCompletionListener(new OnCompletionListener() { @Overridepublic void onCompletion(MediaPlayer mp) {// TODO Auto-generated method stub // mTimer.cancel();//取消定时器current++;prepareAndPlay(current); }});} /*** 装载和播放音乐* @param index int index 播放第几首音乐的索引* */protected void prepareAndPlay(int index) {// TODO Auto-generated method stub if (isTimerRunning) {//如果Timer正在运行mTimer.cancel();//取消定时器isTimerRunning=false;} if (index>2) {current=index=0;}if (index<0) {current=index=2;}//发送广播停止前台Activity更新界面Intent intent=new Intent();intent.putExtra("current", index);intent.setAction(ConstUtil.MUSICBOX_ACTION);sendBroadcast(intent);try {//获取assets目录下指定文件的AssetFileDescriptor对象AssetFileDescriptor assetFileDescriptor=assetManager.openFd(musics[current]);mediaPlayer.reset();//初始化mediaPlayer对象mediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(), assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength());//准备播放音乐mediaPlayer.prepare();//播放音乐mediaPlayer.start();//getDuration()方法要在prepare()方法之后,否则会出现Attempt to call getDuration without a valid mediaplayer异常MusicBox.skbMusic.setMax(mediaPlayer.getDuration());//设置SeekBar的长度} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}//----------定时器记录播放进度---------//mTimer = new Timer();mTimerTask = new TimerTask() {@Overridepublic void run() { isTimerRunning=true;if(isChanging==true)//当用户正在拖动进度进度条时不处理进度条的的进度return; MusicBox.skbMusic.setProgress(mediaPlayer.getCurrentPosition());}}; //每隔10毫秒检测一下播放进度mTimer.schedule(mTimerTask, 0, 10); }@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn null;} //创建广播接收器用于接收前台Activity发去的广播class MusicSercieReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stubint control=intent.getIntExtra("control", -1);switch (control) {case ConstUtil.STATE_PLAY://播放音乐if (state==ConstUtil.STATE_PAUSE) {//如果原来状态是暂停mediaPlayer.start(); }else if (state!=ConstUtil.STATE_PLAY) {prepareAndPlay(current);}state=ConstUtil.STATE_PLAY;break;case ConstUtil.STATE_PAUSE://暂停播放if (state==ConstUtil.STATE_PLAY) {mediaPlayer.pause();state=ConstUtil.STATE_PAUSE;}break;case ConstUtil.STATE_STOP://停止播放if (state==ConstUtil.STATE_PLAY||state==ConstUtil.STATE_PAUSE) {mediaPlayer.stop();state=ConstUtil.STATE_STOP;}break;case ConstUtil.STATE_PREVIOUS://上一首prepareAndPlay(--current);state=ConstUtil.STATE_PLAY;break;case ConstUtil.STATE_NEXT://下一首 prepareAndPlay(++current);state=ConstUtil.STATE_PLAY;break;default:break;}}} }
常量工具类(ConstUtil.java):

package com.jph.util;
/*** Describe:
*
常量工具类*
主要用于为其它类提供程序所用到的常量*
@author jph*
Date:2014.08.07* */ public class ConstUtil {//MusicBox接收器所能响应的Actionpublic static final String MUSICBOX_ACTION="com.jph.musicbox.MUSICBOX_ACTION";//MusicService接收器所能响应的Actionpublic static final String MUSICSERVICE_ACTION="com.jph.musicbox.MUSICSERVICE_ACTION";//初始化flagpublic static final int STATE_NON=0x122;//播放的flagpublic static final int STATE_PLAY=0x123;//暂停的flagpublic static final int STATE_PAUSE=0x124;//停止放的flagpublic static final int STATE_STOP=0x125;//播放上一首的flagpublic static final int STATE_PREVIOUS=0x126;//播放下一首的flagpublic static final int STATE_NEXT=0x127;//菜单关于选项的itemIdpublic static final int MENU_ABOUT=0x200;//菜单退出选的项的itemIdpublic static final int MENU_EXIT=0x201;public ConstUtil() {// TODO Auto-generated constructor stub}}
项目清单配置文件:AndroidManifest.xml:








本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部