需求:项目需要实现扫描本地sdcard上的所有音乐.并且可以进行播放,带可拖动进度条。
实现步骤:1.每个音乐文件在数据中有一条记录,开启一个线程查找数据库找出所有音乐文件,根据后缀名进行过滤,用handle通知ListView展示
2.ListView每一行设置单击事件,选中的那首歌曲进行播放。
3.ListView每一行都有seekBar,根据item选中进行显示隐藏。
1. activity文件 SelectMusicActivity.java
public class SelectMusicActivity extends Activity{
private final static int MUSIC_SCARCH_FINISH = 1;//音乐扫描完成
private ProgressDialog mProgressDialog;
private List<MusicFile> musicFiles=new ArrayList<MusicFile>();
private ListView listMusic;
private MyAdapter myAdapter;
private boolean isPlaying;//是否正在播放
private int currentPosition = -1;
private ViewHolder currentHolder;
private MediaPlayer mediaPlayer=new MediaPlayer();//音乐播放工具
private Handler mHandler=new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case MUSIC_SCARCH_FINISH://音乐扫描完成
mProgressDialog.dismiss();
listMusic.setAdapter(myAdapter=new MyAdapter());
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_music);
getMusicFloder();//查询本地所有音乐
listMusic=(ListView) findViewById(R.id.list_music);
}
@Override
protected void onDestroy() {
super.onDestroy();
if(null!=mediaPlayer){
mediaPlayer.release();
mediaPlayer=null;
isPlaying=false;
}
}
//-------------------------私有类 私有方法---------------------
private class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
// TODO Auto-generated method stub
return musicFiles.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return musicFiles.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@SuppressLint("ResourceAsColor")
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if(null==convertView){
holder=new ViewHolder();
convertView = LayoutInflater.from(SelectMusicActivity.this).inflate(R.layout.item_music_file,parent,false);
holder.musicInfo=(LinearLayout) convertView.findViewById(R.id.music_info);
holder.ivPlayState=(ImageView) convertView.findViewById(R.id.iv_play_state);
holder.musicFolderName=(TextView) convertView.findViewById(R.id.music_folder_name);
holder.musicDuration=(TextView) convertView.findViewById(R.id.music_duration);
holder.rlMusicCapture=(RelativeLayout) convertView.findViewById(R.id.rl_music_capture);
holder.sbProgress=(SeekBar) convertView.findViewById(R.id.sb_progress);
holder.txtStartTime=(TextView) convertView.findViewById(R.id.txt_start_time);
holder.txtEndTime=(TextView) convertView.findViewById(R.id.txt_end_time);
convertView.setTag(holder);
}else{
holder=(ViewHolder) convertView.getTag();
}
MusicFile musicFile=musicFiles.get(position);
holder.musicFolderName.setText(musicFile.getName().substring(1));
holder.musicDuration.setText(Utils.getMusicDuration(musicFile.getMusicDuration()));
holder.txtEndTime.setText(Utils.getMusicDuration(musicFile.getMusicDuration()));
holder.sbProgress.setMax(musicFile.getMusicDuration());
if (position == currentPosition) {
holder.rlMusicCapture.setVisibility(View.VISIBLE);
holder.musicInfo.setBackgroundColor(R.color.mainColor);
}else{
holder.rlMusicCapture.setVisibility(View.GONE);
holder.musicInfo.setBackgroundColor(android.R.color.white);
}
holder.musicInfo.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
itemClick(holder,position);
}
});
holder.sbProgress.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
@Override
public void onStartTrackingTouch(SeekBar seekBar){}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {
if(fromUser){
if(mediaPlayer != null && isPlaying){
mediaPlayer.seekTo(progress);
holder.txtStartTime.setText(Utils.getMusicDuration(progress));
}
}
}
});
return convertView;
}
}
/**
* 相当于List的点击事件
* @param holder
* @param position
*/
@SuppressLint("ResourceAsColor")
private void itemClick(ViewHolder holder,int position){
MusicFile musicFile=musicFiles.get(position);
if(position==currentPosition){//选中当前歌曲
if(isPlaying){//播放中
holder.ivPlayState.setImageResource(R.drawable.button_music_normal);
mediaPlayer.pause();
isPlaying=false;
//position=-1的时候会隐藏下面的seekbar 并且背景颜色设置成白色
position = -1;
myAdapter.notifyDataSetChanged();
}else{//暂停中
holder.ivPlayState.setImageResource(R.drawable.button_music_selected);
mediaPlayer.start();
isPlaying=true;
}
}else{//选中其他歌曲
if(currentPosition==-1){//第一次选中歌曲
holder.ivPlayState.setImageResource(R.drawable.button_music_selected);
musicPlay(musicFile.getDir());
}else{
musicPlay(musicFile.getDir());
currentHolder.ivPlayState.setImageResource(R.drawable.button_music_normal);
holder.ivPlayState.setImageResource(R.drawable.button_music_selected);
}
}
currentPosition = position;
myAdapter.notifyDataSetChanged();
currentHolder=holder;
}
private class ViewHolder{
private LinearLayout musicInfo;
private ImageView ivPlayState;
private TextView musicFolderName;
private TextView musicDuration;
private RelativeLayout rlMusicCapture;//播放截取
private SeekBar sbProgress;//截取进度条
private TextView txtStartTime;//截取开始时间
private TextView txtEndTime;//截取结束时间
}
/**
* 播放歌曲
*/
private void musicPlay(String musicFile){
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(musicFile);
mediaPlayer.prepare();
mediaPlayer.start();
isPlaying = true;
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 利用ContentProvider扫描手机中的音乐,此方法在运行在子线程中完成音乐的扫描,获取所有音乐文件
*/
private void getMusicFloder() {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
Toast.makeText(this, "没有sdcard", 0).show();
return;
}
// 显示进度条
mProgressDialog = ProgressDialog.show(this,null,"正在加载中");
new Thread(new Runnable() {
@Override
public void run() {
//查询音乐
Uri mImageUri = Media.EXTERNAL_CONTENT_URI;
ContentResolver mContentResolver = SelectMusicActivity.this.getContentResolver();
String selection=Media.MIME_TYPE + "=? ";
String[] selectionArgs=new String[]{"audio/mpeg"};
Cursor mCursor = mContentResolver.query(mImageUri,null,selection,selectionArgs,Media.DATE_MODIFIED);
while (mCursor.moveToNext()) {
String path = mCursor.getString(mCursor.getColumnIndex(MediaStore.Audio.Media.DATA));
int duration= mCursor.getInt(mCursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
MusicFile musicFile=new MusicFile();
musicFile.setDir(path);
musicFile.setMusicDuration(duration);
musicFiles.add(musicFile);
}
mCursor.close();
// 通知Handler扫描图片完成
mHandler.sendEmptyMessage(MUSIC_SCARCH_FINISH);
}
}).start();
}
}
2.音乐文件对应实体类 MusicFile.java
/**
* 音乐文件对应实体类
*/
public class MusicFile{
private String dir;//音乐绝对路径
private String name;//音乐名称
private int musicDuration;//音乐时长
public String getDir() {
return dir;
}
public void setDir(String dir) {
this.dir = dir;
int lastIndexOf = this.dir.lastIndexOf("/");
this.name = this.dir.substring(lastIndexOf);
}
public String getName() {
return name;
}
public int getMusicDuration() {
return musicDuration;
}
public void setMusicDuration(int musicDuration) {
this.musicDuration = musicDuration;
}
}
public class Utils {
/**
* 判断文件是否是图片
* @param fileName
* @return
*/
public static boolean isImage(String fileName){
if (fileName.endsWith(".jpg")|| fileName.endsWith(".JPG")|| fileName.endsWith(".png")|| fileName.endsWith(".PNG")
|| fileName.endsWith(".jpeg")|| fileName.endsWith(".JPEG")|| fileName.endsWith(".gif")|| fileName.endsWith(".GIF"))
return true;
return false;
}
/**
* 根据资源ID得到字符串
* @param context
* @param resId
* @return
*/
public static String getStringByResId(Context context,int resId){
return context.getString(resId);
}
public static String getMusicDuration(int duration){
SimpleDateFormat sdf=new SimpleDateFormat("mm:ss");
return sdf.format(duration);
}
}
4.activity_select_music.xml 里面就一个ListView
<?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="vertical" >
<ListView
android:id="@+id/list_music"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
5.ListView的Item布局文件 item_music_file.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:id="@+id/music_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<ImageView
android:id="@+id/iv_play_state"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@drawable/button_music_normal" />
<TextView
android:id="@+id/music_folder_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="4"
android:gravity="left"
android:maxLines="1"
android:text="本地声音文件名称"
android:textSize="16sp" />
<TextView
android:id="@+id/music_duration"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="9dp"
android:layout_weight="1"
android:gravity="right"
android:text="0:00"
android:textColor="#848484"
android:textSize="14sp" />
</LinearLayout>
<RelativeLayout
android:id="@+id/rl_music_capture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/music_info"
android:background="#1D1D1D"
android:padding="9dp">
<SeekBar
android:id="@+id/sb_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/txt_start_time"
android:layout_gravity="center_vertical"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:maxHeight="36dip"
android:minHeight="36dip"
android:paddingLeft="20dp"
android:paddingRight="12dp"
android:background="#1D1D1D"
android:progressDrawable="@drawable/bg_bar"
android:thumb="@drawable/icon_seekbar_pointer"
android:thumbOffset="18dp" />
<TextView
android:id="@+id/txt_start_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="9dp"
android:text="0:00"
android:textColor="#AFAFAF"
android:textSize="16sp" />
<TextView
android:id="@+id/txt_end_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="4dp"
android:text="4:50"
android:textColor="#AFAFAF"
android:textSize="16sp" />
</RelativeLayout>
</RelativeLayout>
效果图如下:
以上就是所有的源码跟效果图,有需要的朋友可以参考一下。推荐下自己创建的android QQ群:202928390 欢迎大家的加入
推荐一个Android开发者必关注公众号,每周都有原创干货