Android 酷炫来袭:制作属于你自己的音频播放器(综合运用MediaPlayer、Service、Broadcast、ListView、SeekBar)

时间:2021-06-03 18:20:05

  Android 酷炫来袭:制作属于你自己的音频播放器(综合运用MediaPlayer、Service、Broadcast、ListView、SeekBar)
  今天制作了一个属于自己的音乐播放器感觉还不错,分享出来,希望能够帮助大家。感觉知识点挺多的,也挺使用的,大大提高了个人兴趣,哈哈,我是程序员啊程序员。
为了有所侧重,我将注意点和学习点放在文章的最开篇。

一、学习重点与注意点

1、Mediaplayer的生命周期、相关方法及其使用
2、如何自定义SeekBar
3、接收广播的动态注册与注销
4、获取文件路径
5、获取歌曲的名称、作者名、图片
6、Service服务的使用

二、Mediaplayer介绍

  想要制作一个属于自己的风格样式的音乐播放器,首先我们要学会使用音乐播放器。

Mediaplayer的生命周期

具体的查看API,这里附一张生命周期图。
Android 酷炫来袭:制作属于你自己的音频播放器(综合运用MediaPlayer、Service、Broadcast、ListView、SeekBar)
  Mediaplayer的证明周期中我们可以看出,Mediaplayer开始的时候需要调用reset()方法,然后是setDataResource()-prepare()-start()在MediaPlayer开启之后,我们可以让它暂停和停止等操作。
reset():将Mediaplayer对象重置到刚刚创建的状态。
setDataResource():设置要播放的音频文件的位置。
prepare():在开始播放之前调用这个方法完成准备工作(使用之前需要设置prepare监听)。
start():开始或继续播放音频文件
seekTo():从指定位置开始播放
stop():停止播放音频。
getDuration():获取载入的音频文件的时长
getCurrentPosition():获取音频文件的当前播放位置

简单的使用方法

点击按钮设置音频播放

public class MainActivity extends Activity implements OnClickListener{
private Button mbtn_start;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mbtn_start=(Button) findViewById(R.id.bt_start);
mbtn_start.setOnClickListener(this);
//获取文件路径,如果我们不知道文件具体放在那里可以通过log打印出来

File musicDir=Environment.getExternalStorageDirectory();
Log.d("音乐", Environment.getExternalStorageDirectory().getAbsolutePath());

musicDir = new File(musicDir, "/musics");

Toast.makeText(getApplicationContext(), Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath(),
Toast.LENGTH_LONG).show();
File[] files=musicDir.listFiles();//获取所有的文件
for(File file:files){
Log.d("路径", file.getAbsolutePath());
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_start:
//new 一个新Mediaplayer对象,按照生命周期顺序操作
MediaPlayer mediaplayer=new MediaPlayer();
mediaplayer.reset();
File musicDir=Environment.getExternalStorageDirectory();

File[] files=musicDir.listFiles();//获取所有的文件
for(File file:files){
Log.d("路径", file.getAbsolutePath());
}
try {

mediaplayer.setDataSource(files[23].getAbsolutePath());
mediaplayer.prepare();
//设置prepare监听器,查看是否准备好,可以开始?
mediaplayer.setOnPreparedListener(new OnPreparedListener() {

@Override
public void onPrepared(MediaPlayer mp) { //准备好了之后开始播放
mp.start();

}
});
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;

default:
break;
}
}
}

注意:我们还需要在manifest中获取读sdcard的权限。

三、制作音频播放器

Ⅰ 开启音乐并使音乐能够在后台运行

1、制作布局,ListView(+子布局+Adapter)+SeekBar+TextView+ToggleButton
2、循序渐进:书写MusicService类继承Service (这里别忘记在manifest中注册),为了保证音乐能够在后台运行,在之后的步骤中我们将在MusicService中创建线程,开启音乐。
3、开启MusicService:在MainActivity中获得文件路径,通过Intent的putStringArrayListExtra的方法传递给MusicService,并监听listview的item点击事件找到要播放的文件的position传递给Service。
4、在MusicService中创建线程,开启音乐

①布局+ListView+子布局+Adapter

在布局中我们顺便学习一下自定义SeekBar样式
新建xml文件,设置点击图片

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/list_btn_radio_check_on" android:state_focused="true" android:state_window_focused="true"></item>
<item android:drawable="@drawable/list_btn_radio_check_on" android:state_selected="true" android:state_window_focused="true"></item>
<item android:drawable="@drawable/list_btn_radio_check_on" android:state_pressed="true" android:state_window_focused="true"></item>
<item android:drawable="@drawable/list_btn_radio_check_off" ></item>
</selector>

SeekBar引用(通过设置Thumb)

  <SeekBar
android:id="@+id/seekbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:progress="20"
android:thumb="@drawable/seekbarimg"
android:layout_weight="1"/>

Adapter


public class MusicAdapter extends BaseAdapter {
private LayoutInflater minflate;
//传递所有文件路径
private File[] musicDirs;

public MusicAdapter(LayoutInflater minflate, File[] musicDirs) {
super();
this.minflate = minflate;
this.musicDirs = musicDirs;
}

@Override
public int getCount() {
// TODO Auto-generated method stub
return musicDirs.length;
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vh = null;
if (convertView == null) {
vh = new ViewHolder();
convertView = minflate.inflate(R.layout.item_music_name, null);
vh.mtextview = (TextView) convertView
.findViewById(R.id.textview_music_name);
vh.mtextview_author = (TextView) convertView
.findViewById(R.id.textview_author_name);
vh.img = (ImageView) convertView.findViewById(R.id.img);
convertView.setTag(vh);
} else {
vh = (ViewHolder) convertView.getTag();
}
vh.mtextview.setText(musicDirs[position].getName());
//通过MediaMetadataRetriever的对象来获取音频文件的
//歌名、歌手、自带的图片
MediaMetadataRetriever mnr = new MediaMetadataRetriever();
Log.d("路径", musicDirs[position].getAbsolutePath());
mnr.setDataSource(musicDirs[position].getAbsolutePath());
String author = mnr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
//获取作者名,不为空对textview进行重新设置
if (author != null) {
vh.mtextview_author.setText(author);
} else {
vh.mtextview_author.setText("<未知>");
}
//获取二进制图片
byte[] img = mnr.getEmbeddedPicture();
if (img != null) {
//将二进制文件转换成位图进行添加专辑图片
Bitmap bitmap = BitmapFactory.decodeByteArray(img, 0, img.length);
vh.img.setImageBitmap(bitmap);
} else {
vh.img.setImageResource(R.drawable.audio_identify_singer_default);
}

return convertView;
}

class ViewHolder {
TextView mtextview;
TextView mtextview_author;
ImageView img;
}
}

这里我们将重点学习的地方提取出来。
获取作者与图片

//通过MediaMetadataRetriever的对象来获取音频文件的
//歌名、歌手、自带的图片
MediaMetadataRetriever mnr = new MediaMetadataRetriever();
Log.d("路径", musicDirs[position].getAbsolutePath());
mnr.setDataSource(musicDirs[position].getAbsolutePath());
String author = mnr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
    //获取二进制图片
byte[] img = mnr.getEmbeddedPicture();
if (img != null) {
//将二进制文件转换成位图进行添加专辑图片
Bitmap bitmap = BitmapFactory.decodeByteArray(img, 0, img.length);
vh.img.setImageBitmap(bitmap);
} else {
vh.img.setImageResource(R.drawable.audio_identify_singer_default);
}

②获取并传递音频文件路径,开启Service

musicDir = Environment.getExternalStorageDirectory();
musicDir = new File(musicDir, "/musics");
files = musicDir.listFiles();
Intent intent = new Intent(getApplicationContext(), MusicService.class);

intent.putStringArrayListExtra("all_music_path", files_path);

startService(intent);

监听ListView
在这里每次点击后开启服务,设置开始键样式为
Android 酷炫来袭:制作属于你自己的音频播放器(综合运用MediaPlayer、Service、Broadcast、ListView、SeekBar)

    @Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
//设置为选中状态,样式改变
mradoibutton_start.setChecked(true);
Intent intent = new Intent(getApplicationContext(), MusicService.class);
intent.putExtra("type", Config.START_NEW_MUSIC_LISTVIEW);
intent.putExtra("music_position",position );
intent.putExtra("all_music_path", files_path);
startService(intent);
}

③Service中创建线程,开启音乐

在onStartCommand方法中调用而不是onCreate方法 ,因为在每次服务启动的时候该方法都会调用,而onCreate方法则是只有在服务被创建的时候才被调用。

  public void  startNewMusiclistview(){
if(mediaplayer==null){
mediaplayer=new MediaPlayer();
}
mediaplayer.reset();
try {

mediaplayer.setDataSource(musicspath.get(musicposition).toString());
mediaplayer.prepare();
mediaplayer.setOnPreparedListener(new OnPreparedListener() {

@Override
public void onPrepared(MediaPlayer mp) {
mediaplayer.start();

mediaplayer.getCurrentPosition();
int duration=mediaplayer.getDuration();
Intent intent2=new Intent("play");
intent2.putExtra("type", 0);
intent2.putExtra("totaltime",mediaplayer.getDuration());
intent2.putExtra("ischecked", true);
//这里发送广播给MainActivity,将总时间传递给SeekBar
sendBroadcast(intent2);
//开启线程,发送广播给MainActivity
//用于与seekbar关联,设置SeekBar进度
MyThreadPlay myplaythread=new MyThreadPlay();
myplaythread.start();
}
});
//为了循环播放音乐,对当前音频的播放完成情况进行检测
//使它能够在播放完一首歌曲之后播放下一首歌曲
mediaplayer.setOnCompletionListener(new OnCompletionListener() {

@Override
public void onCompletion(MediaPlayer mp) {
//最后一个文件时,让位置重新回到开始,通过递归进行循环播放
if(musicposition==musicspath.size()-1){
musicposition=0;
}else{
musicposition++;
}
startNewMusiclistview();
}
});
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Ⅱ创建线程,发送广播与SeekBar可拖动滚动条关联

①由音频文件属性设置Seekbar进度

MusicService中发送广播

 class MyThreadPlay extends Thread{
@Override
public void run() {
while(mediaplayer.isPlaying()){
Intent intent=new Intent("play");
intent.putExtra("type", 1);
intent.putExtra("currentime", mediaplayer.getCurrentPosition());

sendBroadcast(intent);

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
}

MainActivity接收
注意接收者在mainActivity中的动态注册与注销
动态注册BroadcastReceiver

receiver = new MyReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("play");
registerReceiver(receiver, filter);

BroadcastReceiver的继承类

//该类用于接收MusicService发过来的广播,用于设置textview与seekbar
class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

int type = intent.getIntExtra("type", 0);
//由于我们获得的时间是毫秒数,因此要进行相应转换
Date date = new Date();
SimpleDateFormat format=new SimpleDateFormat("mm:ss");
//通过判断intent的type来确定设置进度还是设置时间
switch (type) {
case 0:
int duration = intent.getIntExtra("totaltime", 0);

date.setTime(duration);

String format_duration= format.format(date);
//设置seekbar最大值,这样才能控制进度
mseekbar.setMax(duration);
mtv_totaltime.setText("" + format_duration);
break;
case 1:
currenttime = intent.getIntExtra("currentime", 0);

date.setTime(currenttime);
String format_currenttime= format.format(date);
mtv_currenttime.setText(format_currenttime);
mseekbar.setProgress(currenttime);
break;
default:
break;
}
}
}

注销BroadcastReceiver

    @Override
protected void onDestroy() {

super.onDestroy();
unregisterReceiver(receiver);
}

②通过监听SeekBar的进度改变音频文件进度

上面的代码中我们只实现了音频文件对SeekBar进度的改变时不行的,下面我们通过对SeekBar的监听来改变音频文件

mseekbar.setOnSeekBarChangeListener(this);
  //SeekBar改变过程中时调用
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
}
//SeekBar开始改变时调用
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
//SeekBar最终停止改变时调用,我们在这个方法中进行对音频文件的进度修改
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
Intent intent = new Intent(getApplicationContext(), MusicService.class);
intent.putExtra("type", Config.SEEKTO);
intent.putExtra("progress", mseekbar.getProgress());
startService(intent);

}

MusicService中进行修改进度

            int progress=intent.getIntExtra("progress", 0);
mediaplayer.seekTo(progress);

Ⅲ上一曲、下一曲、开始、停止按钮的监听

MainActivity
上一曲、下一曲的监听只是传递的类型不同,只有停止开始按钮不太一样,因为它在开始与停止状态的图片有变化。

@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), MusicService.class);
switch (v.getId()) {
case R.id.bt_previeous:
intent.putExtra("type", Config.SELECT_PREVIOUS_BY_TOGGLEBUTTON);
startService(intent);
break;
case R.id.bt_next:
intent.putExtra("type", Config.SELECT_NEXT_BY_TOGGLEBUTTON);
startService(intent);
break;
case R.id.bt_start:
if(flag){
intent.putExtra("type", Config.START_NOW_BY_TOGGLEBUTTON);
intent.putExtra("mcurrenttime",currenttime);
startService(intent);
flag=!flag;
}else{
intent.putExtra("type", Config.PAUSE_NOW_BY_TOGGLEBUTTON);
startService(intent);
flag=!flag;
}

break;
default:
break;
}

MusicService中的只是把当前文件位置进行加、减、暂停、继续

int type=intent.getIntExtra("type",222);
switch (type) {
case Config.START_NEW_MUSIC_LISTVIEW:
musicposition=intent.getIntExtra("music_position", 0);
currentposition=musicposition;
startNewMusiclistview();
break;
case Config.SEEKTO:
int progress=intent.getIntExtra("progress", 0);
mediaplayer.seekTo(progress);
break;
case Config.START_NOW_BY_TOGGLEBUTTON:
int currenttime=intent.getIntExtra("mcurrenttime", 0);
while (!mediaplayer.isPlaying()) {
mediaplayer.start();
}


// startNewMusiclistview();
break;
case Config.PAUSE_NOW_BY_TOGGLEBUTTON:
while (mediaplayer.isPlaying()) {
mediaplayer.pause();
}

break;
case Config.SELECT_PREVIOUS_BY_TOGGLEBUTTON:
Log.d("musicString",currentposition +"");
if(currentposition==0){
musicposition=musicspath.size()-1;

}else{
musicposition--;

}
currentposition=musicposition;
startNewMusiclistview();
break;
case Config.SELECT_NEXT_BY_TOGGLEBUTTON:
if(currentposition==musicspath.size()-1){
musicposition=0;
}else{
musicposition++;
}
currentposition=musicposition;
startNewMusiclistview();
break;
case 222:break;
default:
break;
}

ⅣConfig.class文件

该文件中专门用于存放判别type的常量

package com.example.mymediaplayerdemo;

public class Config {
public static final int START_NEW_MUSIC_LISTVIEW=0x01;
public static final int SEEKTO=0x02;
public static final int START_NOW_BY_TOGGLEBUTTON=0x03;
public static final int PAUSE_NOW_BY_TOGGLEBUTTON=0x04;
public static final int SELECT_PREVIOUS_BY_TOGGLEBUTTON=0x05;
public static final int SELECT_NEXT_BY_TOGGLEBUTTON=0x06;
}

主要代码

MainActivity


public class MainActivity extends Activity implements OnClickListener,
OnSeekBarChangeListener, OnItemClickListener {

private ListView mlistview;
private TextView mtv_currenttime;
private TextView mtv_totaltime;

private ToggleButton mradoibutton_pre;
private ToggleButton mradoibutton_start;
private ToggleButton mradoibutton_next;
private SeekBar mseekbar;

private File musicDir;
private File[] files;
private int seekbarprogress;
private MusicAdapter madapter;
private LayoutInflater inflater;
private MyReceiver receiver;
private ArrayList<String> files_path=new ArrayList<String>();
private int currenttime;
private boolean flag=false;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mradoibutton_pre = (ToggleButton) findViewById(R.id.bt_previeous);
mradoibutton_start = (ToggleButton) findViewById(R.id.bt_start);
mradoibutton_next = (ToggleButton) findViewById(R.id.bt_next);
mseekbar = (SeekBar) findViewById(R.id.seekbar);
mlistview = (ListView) findViewById(R.id.listview);
mtv_totaltime = (TextView) findViewById(R.id.textview_totaltime);
mtv_currenttime = (TextView) findViewById(R.id.textview_currenttime);

receiver = new MyReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("play");
registerReceiver(receiver, filter);

musicDir = Environment.getExternalStorageDirectory();
musicDir = new File(musicDir, "/musics");
files = musicDir.listFiles();

// for (File file : files) {
// Log.d("音乐文件", file.getName() + "路径" + file.getAbsolutePath());
//
// }
for (int i = 0; i < files.length; i++) {

files_path.add(files[i].getAbsolutePath().toString());
Log.d("files_path", files_path.get(i));
}

Intent intent = new Intent(getApplicationContext(), MusicService.class);

intent.putStringArrayListExtra("all_music_path", files_path);

startService(intent);

inflater = getLayoutInflater();
madapter = new MusicAdapter(inflater, files);
mlistview.setAdapter(madapter);
mlistview.setOnItemClickListener(this);

mradoibutton_pre.setOnClickListener(this);
mradoibutton_start.setOnClickListener(this);
mradoibutton_next.setOnClickListener(this);

mseekbar.setOnSeekBarChangeListener(this);

}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
mradoibutton_start.setChecked(true);
Intent intent = new Intent(getApplicationContext(), MusicService.class);
intent.putExtra("type", Config.START_NEW_MUSIC_LISTVIEW);
intent.putExtra("music_position",position );
intent.putExtra("all_music_path", files_path);
startService(intent);
}

class MyReceiver extends BroadcastReceiver {



@Override
public void onReceive(Context context, Intent intent) {

int type = intent.getIntExtra("type", 0);
Date date = new Date();
SimpleDateFormat format=new SimpleDateFormat("mm:ss");
switch (type) {
case 0:
int duration = intent.getIntExtra("totaltime", 0);

date.setTime(duration);

String format_duration= format.format(date);
mseekbar.setMax(duration);
mtv_totaltime.setText("" + format_duration);
break;
case 1:
currenttime = intent.getIntExtra("currentime", 0);

date.setTime(currenttime);
String format_currenttime= format.format(date);
mtv_currenttime.setText(format_currenttime);
mseekbar.setProgress(currenttime);
break;
default:
break;
}

}

}

@Override
protected void onDestroy() {

super.onDestroy();
unregisterReceiver(receiver);
}

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub

}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
Intent intent = new Intent(getApplicationContext(), MusicService.class);
intent.putExtra("type", Config.SEEKTO);
intent.putExtra("progress", mseekbar.getProgress());
startService(intent);

}

@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), MusicService.class);
switch (v.getId()) {
case R.id.bt_previeous:
intent.putExtra("type", Config.SELECT_PREVIOUS_BY_TOGGLEBUTTON);
startService(intent);
break;
case R.id.bt_next:
intent.putExtra("type", Config.SELECT_NEXT_BY_TOGGLEBUTTON);
startService(intent);
break;
case R.id.bt_start:
if(flag){
intent.putExtra("type", Config.START_NOW_BY_TOGGLEBUTTON);
intent.putExtra("mcurrenttime",currenttime);
startService(intent);
flag=!flag;
}else{
intent.putExtra("type", Config.PAUSE_NOW_BY_TOGGLEBUTTON);
startService(intent);
flag=!flag;
}

break;
default:
break;
}
}
}

MusicService


public class MusicService extends Service{
private MediaPlayer mediaplayer;
private int musicposition;
private ArrayList<String> musicspath;
private int currentposition;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(musicspath==null){
musicspath=intent.getStringArrayListExtra("all_music_path");
}

int type=intent.getIntExtra("type",222);
switch (type) {
case Config.START_NEW_MUSIC_LISTVIEW:
musicposition=intent.getIntExtra("music_position", 0);
currentposition=musicposition;
startNewMusiclistview();
break;
case Config.SEEKTO:
int progress=intent.getIntExtra("progress", 0);
mediaplayer.seekTo(progress);
break;
case Config.START_NOW_BY_TOGGLEBUTTON:
int currenttime=intent.getIntExtra("mcurrenttime", 0);
while (!mediaplayer.isPlaying()) {
mediaplayer.start();
}


// startNewMusiclistview();
break;
case Config.PAUSE_NOW_BY_TOGGLEBUTTON:
while (mediaplayer.isPlaying()) {
mediaplayer.pause();
}

break;
case Config.SELECT_PREVIOUS_BY_TOGGLEBUTTON:
Log.d("musicString",currentposition +"");
if(currentposition==0){
musicposition=musicspath.size()-1;

}else{
musicposition--;

}
currentposition=musicposition;
startNewMusiclistview();
break;
case Config.SELECT_NEXT_BY_TOGGLEBUTTON:
if(currentposition==musicspath.size()-1){
musicposition=0;
}else{
musicposition++;
}
currentposition=musicposition;
startNewMusiclistview();
break;
case 222:break;
default:
break;
}



return super.onStartCommand(intent, flags, startId);
}
public void startNewMusiclistview(){
if(mediaplayer==null){
mediaplayer=new MediaPlayer();
}
mediaplayer.reset();
try {

mediaplayer.setDataSource(musicspath.get(musicposition).toString());
mediaplayer.prepare();
mediaplayer.setOnPreparedListener(new OnPreparedListener() {

@Override
public void onPrepared(MediaPlayer mp) {
mediaplayer.start();

mediaplayer.getCurrentPosition();
int duration=mediaplayer.getDuration();
Intent intent2=new Intent("play");
intent2.putExtra("type", 0);
intent2.putExtra("totaltime",mediaplayer.getDuration());
intent2.putExtra("ischecked", true);
sendBroadcast(intent2);

MyThreadPlay myplaythread=new MyThreadPlay();
myplaythread.start();
}
});
mediaplayer.setOnCompletionListener(new OnCompletionListener() {

@Override
public void onCompletion(MediaPlayer mp) {
if(musicposition==musicspath.size()-1){
musicposition=0;
}else{
musicposition++;
}
startNewMusiclistview();
}
});
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class MyThreadPlay extends Thread{
@Override
public void run() {
while(mediaplayer.isPlaying()){
Intent intent=new Intent("play");
intent.putExtra("type", 1);
intent.putExtra("currentime", mediaplayer.getCurrentPosition());
sendBroadcast(intent);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
}
}

Adapter

public class MusicAdapter extends BaseAdapter {
private LayoutInflater minflate;
private File[] musicDirs;

public MusicAdapter(LayoutInflater minflate, File[] musicDirs) {
super();
this.minflate = minflate;
this.musicDirs = musicDirs;
}

@Override
public int getCount() {
// TODO Auto-generated method stub
return musicDirs.length;
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vh = null;
if (convertView == null) {
vh = new ViewHolder();
convertView = minflate.inflate(R.layout.item_music_name, null);
vh.mtextview = (TextView) convertView
.findViewById(R.id.textview_music_name);
vh.mtextview_author = (TextView) convertView
.findViewById(R.id.textview_author_name);
vh.img = (ImageView) convertView.findViewById(R.id.img);
convertView.setTag(vh);
} else {
vh = (ViewHolder) convertView.getTag();
}
vh.mtextview.setText(musicDirs[position].getName());
MediaMetadataRetriever mnr = new MediaMetadataRetriever();
Log.d("路径", musicDirs[position].getAbsolutePath());
mnr.setDataSource(musicDirs[position].getAbsolutePath());
String author = mnr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
if (author != null) {
vh.mtextview_author.setText(author);
} else {
vh.mtextview_author.setText("<未知>");
}
byte[] img = mnr.getEmbeddedPicture();
if (img != null) {
Bitmap bitmap = BitmapFactory.decodeByteArray(img, 0, img.length);
vh.img.setImageBitmap(bitmap);
} else {
vh.img.setImageResource(R.drawable.audio_identify_singer_default);
}
return convertView;
}
class ViewHolder {
TextView mtextview;
TextView mtextview_author;
ImageView img;
}
}