Android第八讲——多媒体(一) 音乐播放器

时间:2022-05-26 03:20:13

Android第八讲——多媒体(一) 音乐播放器
使用MediaPlayer对音频、视频操作:
如何获得MediaPlayer的对象
可以使用直接new的方式:
MediaPlayer mp = new MediaPlayer();
也可以使用create的方式,如:
MediaPlayer mp = MediaPlayer.create(this, R.raw.test);//这时就不用调用setDataSource了

音乐播放器

搭建主界面
现在AndroidManifest中添加权限
< uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE” />
xml中包括展示歌曲内容的ListView、进度条SeekBar、歌曲当前时间、歌曲总时间以及暂停/播放、上一曲、下一曲

<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"
tools:context=".MainActivity"
android:background="@mipmap/guide_background">

<ListView
android:id="@+id/listview_music"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">


</ListView>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">

<TextView
android:id="@+id/textview_music_currentposition"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textColor="@android:color/darker_gray"
/>

<SeekBar
android:id="@+id/seekbar_music"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />

<TextView
android:id="@+id/textview_music_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textColor="@android:color/darker_gray"
android:layout_alignParentRight="true"/>

</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">

<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
/>

<ImageView
android:id="@+id/imageview_music_play_prev"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_marginRight="10dp"
android:src="@mipmap/img_appwidget_play_prev"/>

<ImageView
android:id="@+id/imageview_music_playorpause"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/img_appwidget_play"/>

<ImageView
android:id="@+id/imageview_music_play_next"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_marginLeft="10dp"
android:src="@mipmap/img_appwidget_play_next"/>

</LinearLayout>

</LinearLayout>

</LinearLayout>

给每首歌曲设置布局格式 item_music_listview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">

<LinearLayout
android:id="@+id/linearlayout_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<!-- 歌曲图片,暂时缺省,使用默认-->
<ImageView
android:id="@+id/imageview_music"
android:layout_width="70dp"
android:layout_height="70dp"
android:src="@mipmap/img_background_appwidget91_default"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:id="@+id/textview_music_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:layout_marginLeft="10dp"
android:text="歌曲名"
android:textSize="18sp"/>

<!-- 艺术家、暂时缺省-->
<TextView
android:id="@+id/textview_music_artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginLeft="10dp"
android:text=""/>


</LinearLayout>

</LinearLayout>

</LinearLayout>

创建一个歌曲类 MyMusic
类中包含歌曲的名称,歌曲的路径

/**
* 歌曲类
* Created by Went_Gone on 2015/9/10.
*/
public class MyMusic {
private String musicName;
private String path;

public String getPath() {
return path;
}

public void setPath(String path) {
this.path = path;
}

public String getMusicName() {
return musicName;
}

public void setMusicName(String musicName) {
this.musicName = musicName;
}
MediaMetadataRetriever mmr;
public MyMusic(String path) {
File file = new File(path);
musicName = file.getName();
}
}

在MianActivity中先遍历Music中所有的音乐,将其添加到ListView中(此时需要Adapter)

mMyMusics = new ArrayList<>();//初始化
initMusic();
mMusicAdapter = new MusicAdapter(mMyMusics, getLayoutInflater());
mListView.setAdapter(mMusicAdapter);

private void initMusic() {
File sdcard = Environment.getExternalStorageDirectory();//找到手机Sdcard
File music = new File(sdcard, "/Music");//拼音乐所在的文件夹
musics = music.listFiles();//遍历音乐文件夹中的文件
for (File musicl : musics){
Log.d("Music",musicl.getAbsolutePath());
MyMusic myMusic = new MyMusic(musicl.getAbsolutePath());
mMyMusics.add(myMusic);
}
}

创建一个ListView 的Adapter MusicAdapter.java

/**
* Created by Went_Gone on 2015/9/10.
*/
public class MusicAdapter extends BaseAdapter {
private List<MyMusic> myMusics;
private LayoutInflater mInflater;
private String[] title;

public MusicAdapter(List<MyMusic> myMusics, LayoutInflater mInflater) {
this.myMusics = myMusics;
this.mInflater = mInflater;
}

@Override

public int getCount() {
return myMusics.size();
}

@Override
public Object getItem(int position) {
return position;
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
MyMusic myMusic = myMusics.get(position);
ViewHolder vh = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_music_listview, null);
vh = new ViewHolder();
vh.textViewMusicName = (TextView) convertView.findViewById(R.id.textview_music_name);
vh.imageViewMusic = (ImageView) convertView.findViewById(R.id.imageview_music);
vh.textViewMusicArtist = (TextView) convertView.findViewById(R.id.textview_music_artist);
convertView.setTag(vh);
}
vh = (ViewHolder) convertView.getTag();
vh.textViewMusicName.setText(myMusic.getMusicName());
vh.imageViewMusic.setImageResource(R.mipmap.img_background_appwidget91_default);
return convertView;
}

class ViewHolder {
TextView textViewMusicName;
ImageView imageViewMusic;
TextView textViewMusicArtist;
}
}

此时布局以及音乐都加载到了主界面上,接下来就是让音乐播放了
音乐该怎么播放呢,通过上边一开始的图可以知道大体步骤,先重置,找到要播放的音乐,准备,播放。我们不可能在播放的时候永远打开着界面,如果音乐播放的线程放在UI线程中,假使我们关闭主界面,音乐的线程很可能会被关闭掉。所以我们要尽可能不要让其关闭,所以我们将音乐播放的线程放在“Service(服务)”中去。另外,给ListView添加一个item点击事件,使得点击某首音乐时播放。
关于setOnItemClickListener 现在点击某一首音乐后,向MusicService中发送一个Intent,内部有音乐当前类型(是播放还是暂停还是上、下一曲)由MusicService进行解析判断

 mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(getApplicationContext(), MusicService.class);
intent.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_NEW_START);
intent.putExtra(Config.MUSIC_NAME, musics[position].getAbsolutePath());
musicPosition = position;
startService(intent);
mImageViewPlay.setImageResource(R.mipmap.img_appwidget_pause);
}
});

MusicService中复写方法。要开一个线程,用来给UI线程发送广播,以便于将音乐的进度赋值给进度条。
MusicService中复写方法。要开一个线程,用来给UI线程发送广播,以便于将音乐的进度赋值给进度条。

    class MyMusicThread extends Thread{
@Override
public void run() {
while(player.isPlaying()) {
int currentPosition = player.getCurrentPosition();//得到当前音乐当前播放的时间

//给Activity发送广播,以便于seekBar设置当前进度
Intent intent = new Intent(Config.REGISTER_RECEIVER);
intent.putExtra(Config.TYPE, Config.MUSIC_CURRENT);
intent.putExtra(Config.CURRENTPOSITIO, currentPosition);
sendBroadcast(intent);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

MainActivity中接收广播,用于设置SeekBar的值和音乐总时间及当前播放到的时间

 class MyMusicReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
int type = intent.getIntExtra(Config.TYPE,0);
switch (type){
case Config.MUSIC_DURATION:
int duration = intent.getIntExtra(Config.DURATION,0);
mSeekBar.setMax(duration);
SimpleDateFormat format = new SimpleDateFormat("mm:ss");
String time = format.format(new Date(duration));
mTextViewDuration.setText(""+time);
break;
case Config.MUSIC_CURRENT:
int current = intent.getIntExtra(Config.CURRENTPOSITIO,0);
mSeekBar.setProgress(current);
SimpleDateFormat format1 = new SimpleDateFormat("mm:ss");
String time1 = format1.format(new Date(current));
mTextViewCurrent.setText(""+time1);
break;
case Config.MUSIC_PAUSE:
mImageViewPlay.setImageResource(R.mipmap.img_appwidget_play);
break;
case Config.MUSIC_START:
mImageViewPlay.setImageResource(R.mipmap.img_appwidget_pause);
break;
default:
break;
}
}
}

现在点击某一首音乐后,向MusicService中发送一个Intent,内部有音乐当前类型(是播放还是暂停还是上、下一曲)由MusicService进行解析判断
MusicService中的onStartCommand方法中
首先解析是哪种类型

int type = intent.getIntExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_NEW_START);
 case Config.MUSIC_NEW_START:
//开始播放一首音乐
startNewMusic(intent);
break;

/**
* 开始一首新音乐
* @param intent Activity传过来的Intent
*/
private void startNewMusic(Intent intent) {
String musicPath = intent.getStringExtra(Config.MUSIC_NAME);
if (player == null) {
player = new MediaPlayer();
}
player.reset();
try {
player.setDataSource(musicPath);
player.prepare();
} catch (IOException e) {
e.printStackTrace();
}
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();

int duration = player.getDuration();//得到当前音乐的总时长
Intent intent = new Intent(Config.REGISTER_RECEIVER);
intent.putExtra(Config.TYPE, Config.MUSIC_DURATION);
intent.putExtra(Config.DURATION,duration);
sendBroadcast(intent);

MyMusicThread musicThread = new MyMusicThread();
musicThread.start();//开启线程为了实时传递歌曲播放进度

}
});
}

当音乐播放时就需要有时暂停,有时播放
在Activity中通过点击向Service发送一个Intent,包含类型(暂停/播放)

            case R.id.imageview_music_playorpause:
Intent intent = new Intent(getApplicationContext(),MusicService.class);
intent.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_PAUSE_OR_START);
startService(intent);
break;

在Service中解析类型,在通过判断歌曲是否在播放。

1>如果在播放那么将它暂停,并且发送给Activity一个广播,将暂停/播放的图片重置一下。

2>如果是暂停的,难么放它播放,并且要讲设置SeekBar的线程开起来。

            case Config.MUSIC_PAUSE_OR_START:
//暂停或者播放
startOrPauseMusic();
break;

/**
* 开始或暂停一首歌曲
*/
private void startOrPauseMusic() {
if (player!=null){
if (player.isPlaying()){
player.pause();
Intent intent1 = new Intent(Config.REGISTER_RECEIVER);
intent1.putExtra(Config.TYPE,Config.MUSIC_PAUSE);
sendBroadcast(intent1);
}else {
player.start();
Intent intent1 = new Intent(Config.REGISTER_RECEIVER);
intent1.putExtra(Config.TYPE,Config.MUSIC_START);
sendBroadcast(intent1);
MyMusicThread thread = new MyMusicThread();
thread.start();
}
}
}

只是暂停或播放是不够的,我们设置了进度条,能够显示歌曲的进度,那么如果我们想通过进度条设置歌曲进度怎么办呢?
此时就需要在Seekbar上添加事件监听,当滑动SeekBar后,给Service发送一个Intent将滑动的位置传递过去,让歌曲在此位置上播放
首先是SeekBar

        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}
//当手机滑动结束并离开屏幕时
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
Intent intent = new Intent(getApplicationContext(),MusicService.class);
intent.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_SEEK_TO);
intent.putExtra(Config.PROGRESS,mSeekBar.getProgress());
startService(intent);
}
});

然后Service,解析类型

            case Config.MUSIC_SEEK_TO:
int progress = intent.getIntExtra(Config.PROGRESS,0);
if (player!=null) {
player.seekTo(progress);//将歌曲移动到进度条所显示的进度上
}
break;

我们平时用的音乐播放器是不是还有上、下一首呀
我们将上下一首也添加上去,这时我们就需要分类了。
1.如果我们点击了上一首该怎么办?

            case R.id.imageview_music_play_prev:
//当点击上一首按钮时
Intent intent1 = new Intent(getApplicationContext(),MusicService.class);
intent1.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_PREV);
if (musicPosition!=0) {
intent1.putExtra(Config.MUSIC_NAME, musics[musicPosition-1].getAbsolutePath());
musicPosition--;
}else {
//如果当前播放音乐在第一首,那么在点击上一首就会跳转到最后一首
musicPosition = musics.length;
intent1.putExtra(Config.MUSIC_NAME, musics[musicPosition-1].getAbsolutePath());
musicPosition--;
}
startService(intent1);

2.当点击下一首时

            case R.id.imageview_music_play_next:
//当点击下一首时
Intent intent2 = new Intent(getApplicationContext(),MusicService.class);
intent2.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_NEXT);
if (musicPosition!=musics.length-1) {
intent2.putExtra(Config.MUSIC_NAME, musics[musicPosition+1].getAbsolutePath());
musicPosition++;
}else {
//如果当前播放音乐在最后一首,那么在点击下一首就会跳转到第一首
musicPosition = 0;
intent2.putExtra(Config.MUSIC_NAME, musics[musicPosition].getAbsolutePath());
musicPosition++;
}
startService(intent2);

Activity将Intent传递到Service上,Service通过解析判断是上一首还是下一首

            case Config.MUSIC_PREV:
//播放上一首
if (player!=null){
startNewMusic(intent);
}
break;
case Config.MUSIC_NEXT:
//播放下一首
if (player!=null){
startNewMusic(intent);
}
break;

好啦,现在一个简易的音乐播放器就做好了。后边我们还可以加入更多的功能,像随机播放啦、顺序播放啦…
运行如图:Android第八讲——多媒体(一) 音乐播放器

完整代码:
activity_main.xml

<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"
tools:context=".MainActivity"
android:background="@mipmap/guide_background">

<ListView
android:id="@+id/listview_music"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">


</ListView>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">

<TextView
android:id="@+id/textview_music_currentposition"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textColor="@android:color/darker_gray"
/>

<SeekBar
android:id="@+id/seekbar_music"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />

<TextView
android:id="@+id/textview_music_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textColor="@android:color/darker_gray"
android:layout_alignParentRight="true"/>

</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">

<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
/>

<ImageView
android:id="@+id/imageview_music_play_prev"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_marginRight="10dp"
android:src="@mipmap/img_appwidget_play_prev"/>

<ImageView
android:id="@+id/imageview_music_playorpause"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/img_appwidget_play"/>

<ImageView
android:id="@+id/imageview_music_play_next"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_marginLeft="10dp"
android:src="@mipmap/img_appwidget_play_next"/>

</LinearLayout>

</LinearLayout>

</LinearLayout>

item_music_listview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">

<LinearLayout
android:id="@+id/linearlayout_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<!-- 歌曲图片,暂时缺省,使用默认-->
<ImageView
android:id="@+id/imageview_music"
android:layout_width="70dp"
android:layout_height="70dp"
android:src="@mipmap/img_background_appwidget91_default"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:id="@+id/textview_music_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:layout_marginLeft="10dp"
android:text="歌曲名"
android:textSize="18sp"/>

<!-- 艺术家、暂时缺省-->
<TextView
android:id="@+id/textview_music_artist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginLeft="10dp"
android:text=""/>


</LinearLayout>

</LinearLayout>

</LinearLayout>

MyMusic.java 音乐类

/**
* 歌曲类
* Created by Went_Gone on 2015/9/10.
*/
public class MyMusic {
private String musicName;
private String path;

public String getPath() {
return path;
}

public void setPath(String path) {
this.path = path;
}

public String getMusicName() {
return musicName;
}

public void setMusicName(String musicName) {
this.musicName = musicName;
}

MediaMetadataRetriever mmr;
public MyMusic(String path) {
this.path = path;
File file = new File(path);
musicName = file.getName();
}
}

MainActivity.java 主Activity

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private File[] musics;
private List<MyMusic> mMyMusics;
private ListView mListView;
private MusicAdapter mMusicAdapter;
private SeekBar mSeekBar;
private MyMusicReceiver mReceiver;
private TextView mTextViewDuration;
private TextView mTextViewCurrent;
private ImageView mImageViewPlay;
private ImageView mImageViewPlayPrev;
private ImageView mImageViewPlayNext;
private int musicPosition = 0;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = (ListView) findViewById(R.id.listview_music);
mSeekBar = (SeekBar) findViewById(R.id.seekbar_music);
mImageViewPlay = (ImageView) findViewById(R.id.imageview_music_playorpause);
mTextViewDuration = (TextView) findViewById(R.id.textview_music_duration);
mTextViewCurrent = (TextView) findViewById(R.id.textview_music_currentposition);
mImageViewPlayPrev = (ImageView) findViewById(R.id.imageview_music_play_prev);
mImageViewPlayNext = (ImageView) findViewById(R.id.imageview_music_play_next);
mImageViewPlay.setOnClickListener(this);
mImageViewPlayPrev.setOnClickListener(this);
mImageViewPlayNext.setOnClickListener(this);

mMyMusics = new ArrayList<>();//初始化
initMusic();

mMusicAdapter = new MusicAdapter(mMyMusics, getLayoutInflater());
mListView.setAdapter(mMusicAdapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(getApplicationContext(), MusicService.class);
intent.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_NEW_START);
intent.putExtra(Config.MUSIC_NAME, musics[position].getAbsolutePath());
musicPosition = position;
startService(intent);
mImageViewPlay.setImageResource(R.mipmap.img_appwidget_pause);
}
});

//注册广播
mReceiver = new MyMusicReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(Config.REGISTER_RECEIVER);
registerReceiver(mReceiver, filter);

mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}
//当手机滑动结束并离开屏幕时
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
Intent intent = new Intent(getApplicationContext(),MusicService.class);
intent.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_SEEK_TO);
intent.putExtra(Config.PROGRESS,mSeekBar.getProgress());
startService(intent);
}
});
}

private void initMusic() {
File sdcard = Environment.getExternalStorageDirectory();//找到手机Sdcard
File music = new File(sdcard, "/Music");//拼音乐所在的文件夹
musics = music.listFiles();//遍历音乐文件夹中的文件
for (File musicl : musics){
Log.d("Music",musicl.getAbsolutePath());
MyMusic myMusic = new MyMusic(musicl.getAbsolutePath());
mMyMusics.add(myMusic);
}
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.imageview_music_playorpause:
Intent intent = new Intent(getApplicationContext(),MusicService.class);
intent.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_PAUSE_OR_START);
startService(intent);
break;
case R.id.imageview_music_play_prev:
//当点击上一首按钮时
Intent intent1 = new Intent(getApplicationContext(),MusicService.class);
intent1.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_PREV);
if (musicPosition!=0) {
intent1.putExtra(Config.MUSIC_NAME, musics[musicPosition-1].getAbsolutePath());
musicPosition--;
}else {
//如果当前播放音乐在第一首,那么在点击上一首就会跳转到最后一首
musicPosition = musics.length;
intent1.putExtra(Config.MUSIC_NAME, musics[musicPosition-1].getAbsolutePath());
musicPosition--;
}
startService(intent1);
break;
case R.id.imageview_music_play_next:
//当点击下一首时
Intent intent2 = new Intent(getApplicationContext(),MusicService.class);
intent2.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_NEXT);
if (musicPosition!=musics.length-1) {
intent2.putExtra(Config.MUSIC_NAME, musics[musicPosition+1].getAbsolutePath());
musicPosition++;
}else {
//如果当前播放音乐在最后一首,那么在点击下一首就会跳转到第一首
musicPosition = 0;
intent2.putExtra(Config.MUSIC_NAME, musics[musicPosition].getAbsolutePath());
musicPosition++;
}
startService(intent2);
break;
default:
break;
}
}

class MyMusicReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
int type = intent.getIntExtra(Config.TYPE,0);
switch (type){
case Config.MUSIC_DURATION:
int duration = intent.getIntExtra(Config.DURATION,0);
mSeekBar.setMax(duration);
SimpleDateFormat format = new SimpleDateFormat("mm:ss");
String time = format.format(new Date(duration));
mTextViewDuration.setText(""+time);
break;
case Config.MUSIC_CURRENT:
int current = intent.getIntExtra(Config.CURRENTPOSITIO,0);
mSeekBar.setProgress(current);
SimpleDateFormat format1 = new SimpleDateFormat("mm:ss");
String time1 = format1.format(new Date(current));
mTextViewCurrent.setText(""+time1);
break;
case Config.MUSIC_PAUSE:
mImageViewPlay.setImageResource(R.mipmap.img_appwidget_play);
break;
case Config.MUSIC_START:
mImageViewPlay.setImageResource(R.mipmap.img_appwidget_pause);
break;
default:
break;
}
}
}

@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}

MusicAdapter ListView的Adapter

/**
* Created by Went_Gone on 2015/9/10.
*/
public class MusicAdapter extends BaseAdapter {
private List<MyMusic> myMusics;
private LayoutInflater mInflater;
private String[] title;

public MusicAdapter(List<MyMusic> myMusics, LayoutInflater mInflater) {
this.myMusics = myMusics;
this.mInflater = mInflater;
}

@Override

public int getCount() {
return myMusics.size();
}

@Override
public Object getItem(int position) {
return position;
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
MyMusic myMusic = myMusics.get(position);
ViewHolder vh = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_music_listview, null);
vh = new ViewHolder();
vh.linearLayoutItme = (LinearLayout) convertView.findViewById(R.id.linearlayout_item);
vh.textViewMusicName = (TextView) convertView.findViewById(R.id.textview_music_name);
vh.imageViewMusic = (ImageView) convertView.findViewById(R.id.imageview_music);
vh.textViewMusicArtist = (TextView) convertView.findViewById(R.id.textview_music_artist);
convertView.setTag(vh);
}
vh = (ViewHolder) convertView.getTag();
vh.textViewMusicName.setText(myMusic.getMusicName());
vh.imageViewMusic.setImageResource(R.mipmap.img_background_appwidget91_default);
return convertView;
}

class ViewHolder {
TextView textViewMusicName;
ImageView imageViewMusic;
TextView textViewMusicArtist;
LinearLayout linearLayoutItme;
}
}

MusicService.java Service(后台服务)

/**
* Created by Went_Gone on 2015/9/10.
*/
public class MusicService extends Service {
private MediaPlayer player;

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
int type = intent.getIntExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_NEW_START);
switch (type){
case Config.MUSIC_NEW_START:
//开始播放一首音乐
startNewMusic(intent);
break;
case Config.MUSIC_SEEK_TO:
int progress = intent.getIntExtra(Config.PROGRESS,0);
if (player!=null) {
player.seekTo(progress);//将歌曲移动到进度条所显示的进度上
}
break;
case Config.MUSIC_PAUSE_OR_START:
//暂停或者播放
startOrPauseMusic();
break;
case Config.MUSIC_PREV:
//播放上一首
if (player!=null){
startNewMusic(intent);
}
break;
case Config.MUSIC_NEXT:
//播放下一首
if (player!=null){
startNewMusic(intent);
}
break;
default:
break;
}
return super.onStartCommand(intent, flags, startId);
}

/**
* 开始或暂停一首歌曲
*/
private void startOrPauseMusic() {
if (player!=null){
if (player.isPlaying()){
player.pause();
Intent intent1 = new Intent(Config.REGISTER_RECEIVER);
intent1.putExtra(Config.TYPE,Config.MUSIC_PAUSE);
sendBroadcast(intent1);
}else {
player.start();
Intent intent1 = new Intent(Config.REGISTER_RECEIVER);
intent1.putExtra(Config.TYPE,Config.MUSIC_START);
sendBroadcast(intent1);
MyMusicThread thread = new MyMusicThread();
thread.start();
}
}
}

/**
* 开始一首新音乐
* @param intent Activity传过来的Intent
*/
private void startNewMusic(Intent intent) {
String musicPath = intent.getStringExtra(Config.MUSIC_NAME);
if (player == null) {
player = new MediaPlayer();
}
player.reset();
try {
player.setDataSource(musicPath);
player.prepare();
} catch (IOException e) {
e.printStackTrace();
}
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();

int duration = player.getDuration();//得到当前音乐的总时长
Intent intent = new Intent(Config.REGISTER_RECEIVER);
intent.putExtra(Config.TYPE, Config.MUSIC_DURATION);
intent.putExtra(Config.DURATION,duration);
sendBroadcast(intent);

MyMusicThread musicThread = new MyMusicThread();
musicThread.start();

}
});
}

class MyMusicThread extends Thread{
@Override
public void run() {
while(player.isPlaying()) {
int currentPosition = player.getCurrentPosition();//得到当前音乐当前播放的时间

//给Activity发送广播,以便于seekBar设置当前进度
Intent intent = new Intent(Config.REGISTER_RECEIVER);
intent.putExtra(Config.TYPE, Config.MUSIC_CURRENT);
intent.putExtra(Config.CURRENTPOSITIO, currentPosition);
sendBroadcast(intent);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}