代码已经托管到码云,有兴趣的小伙伴可以下载看看
https://git.oschina.net/joy_yuan/MobilePlayer
效果图:
Android系统提供了MediaScanner,MediaProvider,MediaStore等接口,并且提供了一套数据库表格,通过Content Provider的方式提供给用户。当手机开机或者有SD卡插拔等事件发生时,系统将会自动扫描SD卡和手机内存上的媒体文件,如audio,video,图片等,将相应的信息放到定义好的数据库表格中。在这个程序中,我们不需要关心如何去扫描手机中的文件,只要了解如何查询和使用这些信息就可以了。
MediaStore中定义了一系列的数据表格,通过ContentResolver提供的查询接口,我们可以得到各种需要的信息。下面我们重点介绍查询SD卡上的音乐文件信息。
先来了解一下ContentResolver的查询接口:
Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
Uri:指明要查询的数据库名称加上表的名称,从MediaStore中我们可以找到相应信息的参数,具体请参考开发文档。
Projection: 指定查询数据库表中的哪几列,返回的游标中将包括相应的信息。Null则返回所有信息。
selection: 指定查询条件
selectionArgs:参数selection里有 ?这个符号是,这里可以以实际值代替这个问号。如果selection这个没有?的话,那么这个String数组可以为null。
SortOrder:指定查询结果的排列顺序
一、音乐播放器数据获取
1、根据videoPager里获取本地视频的方法,也是从Android系统里去获取本地音频
/** * 从本地sd卡获取数据,有2中办法 * 1、遍历sd卡,根据后缀名 * 2、从内容提供者中获取,系统有自己会去扫描所有media信息。 * 3/6.0后的系统,需要加上动态权限 */ private void getDataFromLocal() { mediaList=new ArrayList<>(); new Thread(){ @Override public void run() { super.run(); SystemClock.sleep(2000); //根据上下文,去获取内容解析者 ContentResolver resolver = context.getContentResolver(); Uri uri= MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; String[] objs={ MediaStore.Audio.Media.DISPLAY_NAME, //视频文件名称 MediaStore.Audio.Media.DURATION, //视频时长 MediaStore.Audio.Media.SIZE, //文件大小 MediaStore.Audio.Media.DATA, //视频的绝对地址 MediaStore.Audio.Media.ARTIST, //歌曲的演唱者,艺术家(音频可能会有该字段) }; Cursor cursor = resolver.query(uri, objs, null, null, null); if (cursor!=null){ while(cursor.moveToNext()){ MediaItem item=new MediaItem(); String name=cursor.getString(0); //名称 item.setName(name); long duration=cursor.getLong(1); //时长 item.setDuration(duration); long size=cursor.getLong(2); //音频大小 item.setSize(size); String data=cursor.getString(3); //音频的绝对地址 item.setData(data); String artist=cursor.getString(4); //艺术家 item.setArtist(artist); mediaList.add(item); //把每个item数据放到集合中 } cursor.close(); } //发消息,提示加载完media中的audio handler.sendEmptyMessage(0); } }.start(); }
2、上面加载完所有音频数据后,会发消息给handler,handler里去setAdapter
private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (mediaList!=null&&mediaList.size()>0){ //有数据 //设置适配器 myAdapter=new MyAdapter(context,mediaList,isVideo); listview.setAdapter(myAdapter); //Toast.makeText(context,"有数据",Toast.LENGTH_SHORT).show(); nomedia.setVisibility(View.GONE); }else{ //没有数据 //文本显示 Toast.makeText(context,"没有数据",Toast.LENGTH_SHORT).show(); } pb_loding.setVisibility(View.GONE); //progressbar隐藏 } };
3、在公用的MyAdapter里来展示listview的数据
package com.yuanlp.mobileplayer.adapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import com.yuanlp.mobileplayer.R; import com.yuanlp.mobileplayer.bean.MediaItem; import com.yuanlp.mobileplayer.utils.Utils; import java.util.List; /** * Created by 原立鹏 on 2017/7/16. */ public class MyAdapter extends BaseAdapter { private Context context; private List<MediaItem> mediaList; private Utils utils; private boolean isVideo; public MyAdapter(Context context,List<MediaItem> mediaList,boolean isVideo){ this.context=context; this.mediaList=mediaList; this.isVideo=isVideo; utils=new Utils(); } @Override public int getCount() { return mediaList.size(); } @Override public Object getItem(int position) { return mediaList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder=null; if (convertView==null){ View view = LayoutInflater.from(context).inflate(R.layout.medialayout, null); convertView=view; viewHolder=new ViewHolder(); viewHolder.iv_icon= (ImageView) convertView.findViewById(R.id.iv_icon); viewHolder.tv_name= (TextView) convertView.findViewById(R.id.tv_name); viewHolder.tv_time= (TextView) convertView.findViewById(R.id.tv_time); viewHolder.tv_size= (TextView) convertView.findViewById(R.id.tv_size); convertView.setTag(viewHolder); }else{ viewHolder= (ViewHolder) convertView.getTag(); } //得到数据 MediaItem item=mediaList.get(position); viewHolder.tv_name.setText(item.getName()); viewHolder.tv_size.setText(android.text.format.Formatter.formatFileSize(context,item.getSize())); viewHolder.tv_time.setText(utils.stringForTime((int) item.getDuration())); if (!isVideo){ //来自音频,那么就把listview的图片换掉 viewHolder.iv_icon.setImageResource(R.drawable.music_default_bg); } return convertView; } /** * 公共的控件类,里面包含每一行要显示的控件 */ private static class ViewHolder{ ImageView iv_icon; TextView tv_name; TextView tv_time; TextView tv_size; } }
这样本地音乐也能展示并播放,但是播放页面共用的是视频的页面,比较丑,所以后面会做一个音乐专用的播放界面,到时候里面有歌词展示,敬请期待。