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

程序执行效果图:

       

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZmVuZ3l1emhlbmdmYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="音乐播放器项目结构" width="320" height="480">

程序代码:

程序界面类(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:</br>
* </br>基于Service的音乐播发器
* </br>本应用主要实现了:
* </br>1.通过前台Activity发出播放相关的控制信息,以广播的形式
* </br>传递给后台的Service。后台的Service负责音乐的播放。
* </br>并负责接收后台的广播来更新播放界面的歌曲名、歌手名。
* </br>2.通过进度条来显示当前播放的位置,当用户拖动进度条时
* </br>通过OnSeekBarChangeListener事件来控制
* </br>后台的mediaPlayer播放指定位置的音乐。 * </br>@author jph
* </br>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:</br>
* </br>负责音乐播放的后台Service
* </br>1.通过接收来自前台的控制播放信息的广播来播放指定音乐
* </br>2.载入assets文件夹下的音乐
* </br>3.为mediaPlayer的完毕事件创建监听器当当前音乐播放
* </br>完毕后自己主动播放下一首音乐
* </br>4.为每一首正在播放的音乐创建一个定时器,用于检測播放进度
* </br>并更新进度条
* </br>@author jph
* </br>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:</br>
* </br>常量工具类
* </br>主要用于为其他类提供程序所用到的常量
* </br>@author jph
* </br>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:

<?

xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jph.musicbox"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<!-- 去掉主界面的标题栏 -->
<activity
android:name="com.jph.musicbox.MusicBox"
android:label="@string/app_name"
android:theme="@android:style/Theme.Black.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 注冊MusicService -->
<service android:name="com.jph.musicbox.MusicService"></service>
</application> </manifest>

版权声明:本文博客原创文章,博客,未经同意,不得转载。

Android基于发展Service音乐播放器的更多相关文章

  1. 基于jQuery虾米音乐播放器样式代码

    分享一款基于jQuery虾米音乐播放器样式代码.这是一款基于jquery+html5实现的虾米音乐播放器源码下载.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div c ...

  2. 项目源码--Android类似酷狗音乐播放器

    下载源码 知识技能概要: 1.音乐文件的扫描与管理 2.音频流的解码 3. UI控件的综合使用 4.播放列表方式管理 5.随机播放方式 6.源码带详细的中文注释 ...... 详细介绍 1. 音乐文件 ...

  3. Android 仿百度网页音乐播放器圆形图片转圈播放效果

    百度网页音乐播放器的效果  如下 : http://www.baidu.com/baidu?word=%E4%B8%80%E7%9B%B4%E5%BE%88%E5%AE%89%E9%9D%99& ...

  4. QT5:C++实现基于multimedia的音乐播放器(二)

    今天接着上一篇来实现播放器的槽函数. 先来实现播放模式,槽函数如下: //播放模式 void Music::musicPlayPattern() { //z=++z%3; ) { //顺序播放 pla ...

  5. QT5:C++实现基于Multimedia的音乐播放器(序)

    前段时间C++课设,决定做个播放器,于是参考了网上的代码后,做了个很简陋的音乐播放器(只写了MP3格式)出来,虽然功能甚少,但还是决定把过程记录一下. 成品如下图: 播放器功能: 上.下一首,音量控制 ...

  6. Android应用开发--MP3音乐播放器代码实现(一)

    需求1:将内存卡中的MP3音乐读取出来并显示到列表当中 1.   从数据库中查询所有音乐数据,保存到List集合当中,List当中存放的是Mp3Info对象 2.   迭代List集合,把每一个Mp3 ...

  7. Android课程---简单的音乐播放器

    第一个:用Activity实现 activity_music_play1.xml <?xml version="1.0" encoding="utf-8" ...

  8. andorid Activity和Service音乐播放器

    AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xm ...

  9. QT5:C++实现基于multimedia的音乐播放器(一)

    上一篇里简略的描述了一下播放器的实现,这一篇开始具体描述一下过程. 环境配置:Qt Creator 打开Qt Creator,创建一个new project,项目名称随你喜欢(我的是MusicPlay ...

随机推荐

  1. Cocos2d-x游戏的场景结构布局

  2. Eclipse用法和技巧七:自动生成get和set方法2

    上一篇文章中我们介绍了自动批量生成get和set函数的方法.这个方法一般在声明完类的数据域之后使用,比较方便快捷.这里再补充几个自动生成get和set函数的方法. 步骤一:在声明的数据域中按Ctrl+ ...

  3. FireMonkey Style Designer

    http://docwiki.embarcadero.com/RADStudio/Berlin/en/FireMonkey_Style_Designer http://docwiki.embarcad ...

  4. 对 sql server 数据库的备份进行加密

    原文:对 sql server 数据库的备份进行加密 嗯,最近在研究数据库备份相关的东西,考虑到应该为数据库备份加个密,就准备从网上搜索一下看看有什么好办法,没想到还挺乱... 首先,我从网上搜到的, ...

  5. PHP学习之-1.6 PHP语句结束符

    PHP语句结束符 是不是我们在javascript,Java 的每一句代码结束的地方都有一个分号 ";" PHP的结束符号也是 ";". 注意:在PHP编程中需 ...

  6. JavaScript编程:浏览器对象模型BOM

    4.浏览器对象模型BOM: document.body.offsetwidth可以获取浏览器宽度. Window对象:          窗口操作:            1.moveBy(dx,dy ...

  7. Oracle 经常使用的改动语句

    一.表Table 測试表:MY_TEST_TABLE -- Create table create table MY_TEST_TABLE ( A VARCHAR2(30), B NUMBER(10) ...

  8. 使用gradle打包jar包

    近期用android studio来做android开发的IDE,它是使用gradle来构建的,于是開始学习gradle. 如今有一个项目,里面有一个android-library的模块.我想在做re ...

  9. 注解在android中的使用

    注解在android程序中的使用 何为注解: 在Java其中,注解又叫做"元数据",它为我们在源码中加入信息提供了一种形式化的方法.让我们能在以后的某个时间方便的使用这些数据.更确 ...

  10. Incompatible namespaceIDs或连接被对端重置异常的解决

    Workaround 1: Start from scratch I can testify that the following steps solve this error, but the si ...