IT技术问答
联系我们
IT技术问答

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

发布人:admin 发布时间:2019-01-31

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

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

程序运行效果图:

vc=">


程序代码:

程序界面类(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; @Override protected 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); //启动后台Service Intent intent=new Intent(this, MusicService.class); startService(intent); } OnClickListener listener=new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub switch (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() { @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub //当拖动停止后,控制mediaPlayer播放指定位置的音乐 MusicService.mediaPlayer.seekTo(seekBar.getProgress()); MusicService.isChanging=false; } @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub MusicService.isChanging=true; } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // TODO Auto-generated method stub } }; @Override public 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 stub Intent intent=new Intent(); intent.setAction(ConstUtil.MUSICSERVICE_ACTION); intent.putExtra("control", state); //向后台Service发送播放控制的广播 sendBroadcast(intent); } @Override public 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{ @Override public 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; @Override public void onCreate() { // TODO Auto-generated method stub super.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() { @Override public 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 block e.printStackTrace(); } //----------定时器记录播放进度---------// mTimer = new Timer(); mTimerTask = new TimerTask() { @Override public void run() { isTimerRunning=true; if(isChanging==true)//当用户正在拖动进度进度条时不处理进度条的的进度 return; MusicBox.skbMusic.setProgress(mediaPlayer.getCurrentPosition()); } }; //每隔10毫秒检测一下播放进度 mTimer.schedule(mTimerTask, 0, 10); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } //创建广播接收器用于接收前台Activity发去的广播 class MusicSercieReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub int 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接收器所能响应的Action public static final String MUSICBOX_ACTION="com.jph.musicbox.MUSICBOX_ACTION"; //MusicService接收器所能响应的Action public static final String MUSICSERVICE_ACTION="com.jph.musicbox.MUSICSERVICE_ACTION"; //初始化flag public static final int STATE_NON=0x122; //播放的flag public static final int STATE_PLAY=0x123; //暂停的flag public static final int STATE_PAUSE=0x124; //停止放的flag public static final int STATE_STOP=0x125; //播放上一首的flag public static final int STATE_PREVIOUS=0x126; //播放下一首的flag public static final int STATE_NEXT=0x127; //菜单关于选项的itemId public static final int MENU_ABOUT=0x200; //菜单退出选的项的itemId public static final int MENU_EXIT=0x201; public ConstUtil() { // TODO Auto-generated constructor stub } }
项目清单配置文件:AndroidManifest.xml:


    
    
        
        
            
                
                
            
        
        
        
    







http://www.bkjia.com/Androidjc/862066.htmlwww.bkjia.comtruehttp://www.bkjia.com/Androidjc/862066.htmlTechArticleAndroid开发之基于Service的音乐播放器 这是一个基于Service组件的音乐播放器,程序的音乐将会由后台的Service组件负责播放,当后台的播放状...

本文源自: 环亚娱乐

上一篇:android图片处理方法(不断收集中),
下一篇:没有了