手机影音第十四天,本地音乐列表的展示与播放(利用视频播放的布局)

代码已经托管到码云,有兴趣的小伙伴可以下载看看

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;
    }
}

这样本地音乐也能展示并播放,但是播放页面共用的是视频的页面,比较丑,所以后面会做一个音乐专用的播放界面,到时候里面有歌词展示,敬请期待。

时间: 2024-12-24 05:38:40

手机影音第十四天,本地音乐列表的展示与播放(利用视频播放的布局)的相关文章

Chrome浏览器扩展开发系列之十四:本地消息机制Native messagin

Chrome浏览器扩展开发系列之十四:本地消息机制Native messaging 2016-11-24 09:36 114人阅读 评论(0) 收藏 举报  分类: PPAPI(27)  通过将浏览器所在客户端的本地应用注册为Chrome浏览器扩展的"本地消息主机(native messaging host)",Chrome浏览器扩展还可以与客户端本地应用之间收发消息. 客户端的本地应用注册为Chrome浏览器扩展的"本地消息主机"之后,Chrome浏览器会在独立的

扣丁音乐(四)——本地音乐加载

本文出自:http://blog.csdn.net/dt235201314/article/details/51341078 一丶本地音乐加载相当于就是listVIew应用 扣丁音乐1.0前部分(gif图大小限制)演示: 实体类Mp3Info(歌曲相关数据及get和set方法) public class Mp3Info { private long id; private String title;//歌名 private String artist;//艺术家 private String a

手机影音第十五天,利用service实现后台播放音乐,在通知栏显示当前音乐信息等

代码已经托管到码云上,有兴趣的小伙伴可以下载看看 https://git.oschina.net/joy_yuan/MobilePlayer 先来一张目前的音乐播放器的效果图,当播放时,手机的状态通知栏也会有音乐信息显示. 这里可以看到有歌名.演唱者,还有歌曲的总时间,当前播放时间,当前播放进度,音乐暂停.下一首,上一首,音乐循环模式(单曲循环,顺序播放.循环播放)功能的实现.下一步就是把中间空白的部分填充歌词,然后做成根据进度显示歌词. 由于这次的内容有点多,是写了一天半的代码,讲的没那么细,

手机影音第十六天,集成eventbus代替广播

代码已经托管到码云上,有兴趣的小伙伴可以下载看看 https://git.oschina.net/joy_yuan/MobilePlayer 一 EventBus 3.0   ---利用eventbus代替广播来获取音乐的数据. EventBus是一款针对Android优化的发布/订阅事件总线.主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅.以及将发送者和接收者解耦. 1.下载Even

手机影音第十天,控制屏幕上下滑动改变音量变化,监听物理键改变音量

代码已托管至码云上,有兴趣的小伙伴可以下载看看,IDE是Android studio 2.3.2 https://git.oschina.net/joy_yuan/MobilePlayer 常见的手机播放器,都有屏幕上下滑动改变音量大小的功能,在此也实现下: 原理是: 1.从手指触碰屏幕,到离开屏幕,计算滑动的高度差,然后拿这个高度差与屏幕的高对比,最后结合总音量,得到改变的音量,具体的公式如下 : 改变的音量=(滑动距离差/屏幕总高度)*总音量 结束滑动后的音量=触碰屏幕时的音量+改变的音量

Chrome浏览器扩展开发系列之十四:本地消息机制Native messaging

通过将浏览器所在客户端的本地应用注册为Chrome浏览器扩展的“本地消息主机(native messaging host)”,Chrome浏览器扩展还可以与客户端本地应用之间收发消息. 客户端的本地应用注册为Chrome浏览器扩展的“本地消息主机”之后,Chrome浏览器会在独立的进程中启动该本地应用,并通过标准输入/输出流(stdin/stdout)进行消息通信. 1)      本地应用的配置文件的内容 本地应用要能够成为“本地消息主机”,必须有一个manifest.json配置文件(文件名

Android实例-手机安全卫士(十四)-为密码进行MD5加密

一.目标. 将设置的密码通过MD5加密后再保存. 二.代码实现. 1.在自定义工具包(com.example.mobilesafe.ui)中新增一个类(取名MD5Utils).在新建类(MD5Utils)中新建一个返回值为String类型的public的静态方法(取名mD5Encryption),传入参数为String类型(password). 2.在新建的方法(md5Encryption)中: ①.通过消息摘要器对象(MessageDigest)的getInstance(String algo

Django(十四)课程机构列表页数据展示,Django的modelform,关于urls的重新分发

关于urls的重新分发: 如果所有url都配置在根路径的urls.py里,会特别多,而且也不易于修改,Django框架里支持urls的重新分发: 1.在根路径的urls配置上: PS:namespace是定义命名空间,比如下面这种配置, urlpatterns = [ #课程机构url配置,验证码,每个app可以书写自己的url,然后通过include进来 url(r'^org/', include('oraganization.urls',namespace="org")), ] 2

salesforce 零基础学习(四十四)实现checkbox列表简单过滤功能

现在做的项目代码是原来其他公司做的,要在原来基础上业务进行适当调整加上一些CR,其中有一个需要调整的需求如下: 原来使用apex:selectCheckboxes封装了一个checkbox列表,因为数据太多导致显示起来比较丑,用户希望改进一下UI. apex:selectCheckboxes作用原理为解析成html以后变成table标签, 大概层级结构可以分成<table><tbody><tr><td><input type="checkbo