手機影音第十四天,本地音樂列表的展示與播放(利用視頻播放的布局)
代碼已經托管到碼雲,有興趣的小夥伴可以下載看看
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; } }
這樣本地音樂也能展示並播放,但是播放頁面共用的是視頻的頁面,比較醜,所以後面會做一個音樂專用的播放界面,到時候裏面有歌詞展示,敬請期待。
本文出自 “YuanGuShi” 博客,請務必保留此出處http://cm0425.blog.51cto.com/10819451/1951354
手機影音第十四天,本地音樂列表的展示與播放(利用視頻播放的布局)