音乐播放器
MediaPlayer:
利用Environment.getExternalStorageDirectory()方法得到sdcard路径,然后用new File(得到的sdcard父路径,子路径)得到音乐存放路径。用File[]型的数组存放得到的所有音乐文件,接着就可以播放。
用MediaPlay需要在manifests中申请权限android.permission.READ_EXTERNAL_STORAGE。
本实例用于实现一个简单的音乐播放器,用ListView来显示音乐清单。
代码:
public class MainActivity extends Activity {
private Button mButtonStart;
private File[] mMusics;
private ListView mMusicList;
private MusicAdapter mAdapter;
private LayoutInflater mInflater;
private SeekBar mMusicSeekBar;
private TextView mTimeText;
private MusicReceiver mReceiver;
private int duration;
private int currentTime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButtonStart = (Button) findViewById(R.id.button_start_music);
mMusicList = (ListView) findViewById(R.id.list_view_musics);
mMusicSeekBar = (SeekBar) findViewById(R.id.music_seek_bar);
mTimeText = (TextView) findViewById(R.id.text_time);
initMusicData();
mInflater = getLayoutInflater();
mAdapter = new MusicAdapter(mMusics,mInflater);
mMusicList.setAdapter(mAdapter);
mReceiver = new MusicReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.music.play");
registerReceiver(mReceiver, filter);
mMusicList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
changeMusic(mMusics[position]);
}
});
mMusicSeekBar.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) {
changeProgress();
}
});
}
//当拖动SeekBar进度条时调用此方法,向MusicService服务发送进度条的进度,服务器收到消息后会作出让当前播放音频进度同步于进度条的操作
private void changeProgress() {
Intent intent = new Intent(getApplicationContext(),MusicService.class);
int progress = mMusicSeekBar.getProgress();
intent.putExtra("type", Config.CHANGE_PROGRESS);
intent.putExtra("progress",progress);
startService(intent);
}
//当点击ListView时调用该方法,向MusicService发出要更换曲目的消息
private void changeMusic(File mMusic) {
Intent intent = new Intent(getApplicationContext(), MusicService.class);
intent.putExtra("type", Config.CHANGE_MUSIC);
intent.putExtra("musicName", mMusic.getAbsolutePath());
startService(intent);
}
private void initMusicData(){
//得到外部存储中音频文件存储的路径
File musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
mMusics = musicDir.listFiles();
}
//此广播接收器用于接收来自音乐服务的信息,并作出响应
private class MusicReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
int type = intent.getIntExtra("type",0);
switch (type){
case 0:
duration = intent.getIntExtra("duration",0);
mMusicSeekBar.setMax(duration);
//将seekBar进度条的进度容量设定为音频的长度
break;
case 1:
currentTime = intent.getIntExtra("time",0);
mMusicSeekBar.setProgress(currentTime);
mTimeText.setText(myTimeFormat(currentTime)+"/"+myTimeFormat(duration));//将seekbar的进度大小设定为当前音乐播放的进度
break;
default:
break;
}
}
}
@Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
}
//当要将得到的音乐进度和总长度转换为XX(分):XX(秒)形式时调用该函数
public String myTimeFormat(long time){
long miao = time/1000;
long fen = miao/60;
long yumiao = miao%60;
String backTime = "";
if(miao>0){
backTime = fen+":"+yumiao;
}else{
backTime = ""+yumiao;
}
return backTime;
}
//点击后退键不停止活动
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_BACK){
moveTaskToBack(false);
return true;
}
return super.onKeyDown(keyCode, event);
}
}
建立一个服务Service
public class MusicService extends Service {
private MediaPlayer mPlayer;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
int type = intent.getIntExtra("type", 1
);
//判断type以完成不同的操作
switch (type) {
case 0:
startNewMusic(intent);
break;
case 1:
if (mPlayer != null) {
int progress = intent.getIntExtra("progress", 0);
mPlayer.seekTo(progress);//设置曲目进度
}
break;
default:
break;
}
return super.onStartCommand(intent, flags, startId);
}
//此方法用于得到被点击的音频的绝对路径并播放
private void startNewMusic(Intent intent) {
String musicPath = intent.getStringExtra("musicName");
if (mPlayer == null) {
mPlayer = new MediaPlayer();
}
mPlayer.reset();
try {
mPlayer.setDataSource(musicPath);
mPlayer.prepare();
mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
int duration = mPlayer.getDuration();//得到总的播放的时间
Intent intent = new Intent("com.music.play");
intent.putExtra("type", 0);
intent.putExtra("duration", duration);
sendBroadcast(intent);
MusicPlayThread musicPlayThread = new MusicPlayThread();
musicPlayThread.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
//这个线程用于发送音乐播放的进度,理论上每1秒发送一次
class MusicPlayThread extends Thread {
@Override
public void run() {
while (mPlayer.isPlaying()) {
int time = mPlayer.getCurrentPosition();//得到当前播放的时间
Intent intent = new Intent("com.music.play");
intent.putExtra("type", 1);
intent.putExtra("time", time);
sendBroadcast(intent);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
MusicListView的adapter
public class MusicAdapter extends BaseAdapter {
private File[] mMusics;
private LayoutInflater mInflater;
public MusicAdapter(File[] mMusics, LayoutInflater mInflater) {
this.mMusics = mMusics;
this.mInflater = mInflater;
}
@Override
public int getCount() {
return mMusics.length;
}
@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) {
ViewHolder vh = null;
if(convertView==null){
convertView = mInflater.inflate(R.layout.music_item,null);
vh = new ViewHolder();
vh.musicName = (TextView) convertView.findViewById(R.id.text_music_name);
vh.artistImage = (ImageView)convertView.findViewById(R.id.image_artist);
vh.artistName = (TextView) convertView.findViewById(R.id.text_artist_name);
convertView.setTag(vh);
}else{
vh = (ViewHolder) convertView.getTag();
}
String musicName = mMusics[position].getName();
vh.musicName.setText(musicName);
//MediaMetadataRetriever用于得到音乐文件的一些信息,如图片,艺术家等
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
//MediaMetadataRetriever不能加载非音频文件,否则会出错
mmr.setDataSource(mMusics[position].getAbsolutePath());
//得到歌手名
String author = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
if(author!=null){
vh.artistName.setText(author);
}else{
vh.artistName.setText("<未知>");
}
//得到音乐的图片,但很多音频文件不含图片
byte[] image = mmr.getEmbeddedPicture();
if(image!=null){
Bitmap bitmap = BitmapFactory.decodeByteArray(image,0,image.length);
vh.artistImage.setImageBitmap(bitmap);
}else{
vh.artistImage.setImageResource(R.mipmap.photo_nomal);
}
return convertView;
}
class ViewHolder{
ImageView artistImage;
TextView musicName;
TextView artistName;
}
}
布局
<LinearLayout <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">
<ListView
android:id="@+id/list_view_musics"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp">
</ListView>
<Button
android:id="@+id/button_start_music"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:text="开始音乐"/>
<SeekBar
style="?android:attr/seekBarStyle"
android:id="@+id/music_seek_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/text_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingRight="15dp"
android:gravity="right"/>
</LinearLayout>
music_item
<?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:gravity="center_vertical"
android:padding="15dp">
<ImageView
android:id="@+id/image_artist"
android:layout_width="30dp"
android:layout_height="30dp"/>
<TextView
android:id="@+id/text_music_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginLeft="20dp"/>
<TextView
android:id="@+id/text_artist_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"/>
</LinearLayout>
结果展示: