Android之MediaStore

Posted 胖子luffy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android之MediaStore相关的知识,希望对你有一定的参考价值。

在日常开发中,我们经常会使用MediaStore来获取手机的音频、图片、视频等相关信息。下面3个是常见的内部类:

MediaStore.Audio获取音频信息的类

MediaStore.Images获取图片信息

MediaStore.Video获取视频信息

1、MediaStore.Audio

在这个类中我们可以获取音频的专辑、艺术家、流派等等,通过 MediaStore.Audio.AlbumColumns 可以查阅专辑表的字段信息,我们也可以通过Uri来查询手机上的

专辑表的字段信息。主要是用 MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI 的Uri来查询。其中EXTERNAL_CONTENT_URI 为查询外置内存卡的,内置内存卡

为 INTERNAL_CONTENT_URI。
[java] view plain copy

private Uri albumUri = MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI;  

[java] view plain copy

// 配置<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>权限  
    private void getUriColumns(Uri uri)  
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);  
        cursor.moveToFirst();   
        String[] columns = cursor.getColumnNames();  
        for (String string : columns)   
            System.out.println(cursor.getColumnIndex(string)+" = "+string);  
          
      

结果为:

06-24 01:05:44.979: I/System.out(1529): 0 = _id
06-24 01:05:44.983: I/System.out(1529): 1 = album
06-24 01:05:44.987: I/System.out(1529): 2 = album_key
06-24 01:05:44.987: I/System.out(1529): 3 = minyear
06-24 01:05:44.987: I/System.out(1529): 4 = maxyear
06-24 01:05:44.987: I/System.out(1529): 5 = artist
06-24 01:05:44.987: I/System.out(1529): 6 = artist_id
06-24 01:05:44.987: I/System.out(1529): 7 = artist_key
06-24 01:05:44.987: I/System.out(1529): 8 = numsongs
06-24 01:05:44.987: I/System.out(1529): 9 = album_art

可以看到相应的字段和下标是什么。

[java] view plain copy

// 艺术家  
    private Uri artUri = MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI;  
    // 流派  
    private Uri genresUri = MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI;  

也可以通过上面的Uri来查询音频的艺术家和流派相应的信息。

音频信息比较全的是这个类 MediaStore.Audio.Media 可以通过Uri来看下字段有什么:
[java] view plain copy

private Uri mediaUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;  

字段为:

06-24 01:25:51.656: I/System.out(5292): 0 = _id
06-24 01:25:51.656: I/System.out(5292): 1 = _data 音频路径
06-24 01:25:51.656: I/System.out(5292): 2 = _display_name音频名称包括后缀名
06-24 01:25:51.656: I/System.out(5292): 3 = _size 音频大小
06-24 01:25:51.656: I/System.out(5292): 4 = mime_type音频类型
06-24 01:25:51.656: I/System.out(5292): 5 = date_added
06-24 01:25:51.656: I/System.out(5292): 6 = is_drm
06-24 01:25:51.656: I/System.out(5292): 7 = date_modified
06-24 01:25:51.656: I/System.out(5292): 8 = title 音频名称不包括后缀名
06-24 01:25:51.656: I/System.out(5292): 9 = title_key
06-24 01:25:51.664: I/System.out(5292): 10 = duration音频时长
06-24 01:25:51.664: I/System.out(5292): 11 = artist_id
06-24 01:25:51.664: I/System.out(5292): 12 = composer
06-24 01:25:51.664: I/System.out(5292): 13 = album_id
06-24 01:25:51.672: I/System.out(5292): 14 = track
06-24 01:25:51.672: I/System.out(5292): 15 = year
06-24 01:25:51.672: I/System.out(5292): 16 = is_ringtone
06-24 01:25:51.672: I/System.out(5292): 17 = is_music
06-24 01:25:51.672: I/System.out(5292): 18 = is_alarm
06-24 01:25:51.672: I/System.out(5292): 19 = is_notification
06-24 01:25:51.672: I/System.out(5292): 20 = is_podcast
06-24 01:25:51.672: I/System.out(5292): 21 = bookmark
06-24 01:25:51.700: I/System.out(5292): 22 = album_artist
06-24 01:25:51.700: I/System.out(5292): 23 = artist_id:1
06-24 01:25:51.700: I/System.out(5292): 24 = artist_key
06-24 01:25:51.700: I/System.out(5292): 25 = artist
06-24 01:25:51.700: I/System.out(5292): 26 = album_id:1
06-24 01:25:51.700: I/System.out(5292): 27 = album_key
06-24 01:25:51.700: I/System.out(5292): 28 = album

字段很多,就对比较常用的注释了下,有字段是和其他表关联的如 artist_id、album_id等等,其中比较常用的是 _data、 _display_name、 _size、mime_type、 title、duration等字段

可以通过常用的字段来查询手机下相应的音频文件:
[java] view plain copy

private Uri mediaUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;  

[java] view plain copy

private void getUriData(Uri uri)  

        String[] projection = "_data","_display_name","_size","mime_type","title","duration";  
        Cursor cursor = getContentResolver().query(uri, projection, null, null, null);  
        cursor.moveToFirst();  
        do   
            System.out.println("_data = "+cursor.getString(cursor.getColumnIndex("_data")));  
            System.out.println("_display_name = "+cursor.getString(cursor.getColumnIndex("_display_name")));  
            System.out.println("_size = "+cursor.getString(cursor.getColumnIndex("_size")));  
            System.out.println("mime_type = "+cursor.getString(cursor.getColumnIndex("mime_type")));  
            System.out.println("title = "+cursor.getString(cursor.getColumnIndex("title")));  
            System.out.println("duration = "+cursor.getString(cursor.getColumnIndex("duration")));  
         while (cursor.moveToNext());  
      

结果如下:

06-24 13:40:12.445: I/System.out(4610): _data = /mnt/sdcard/kgmusic/download/孙楠、神话、韩红 - 美丽的神话.mp3
06-24 13:40:12.445: I/System.out(4610): _display_name = 孙楠、神话、韩红 - 美丽的神话.mp3
06-24 13:40:12.445: I/System.out(4610): _size = 4635648
06-24 13:40:12.445: I/System.out(4610): mime_type = audio/mpeg
06-24 13:40:12.445: I/System.out(4610): title = 美丽的神话
06-24 13:40:12.445: I/System.out(4610): duration = 289712

06-24 13:40:12.445: I/System.out(4610): _data = /mnt/sdcard/kgmusic/download/那英、孙楠 - 只要有你.mp3
06-24 13:40:12.445: I/System.out(4610): _display_name = 那英、孙楠 - 只要有你.mp3
06-24 13:40:12.445: I/System.out(4610): _size = 4012536
06-24 13:40:12.445: I/System.out(4610): mime_type = audio/mpeg
06-24 13:40:12.445: I/System.out(4610): title = 只要有你( 少年包青天 片尾曲)
06-24 13:40:12.446: I/System.out(4610): duration = 250784

由于音频过多就列举了两个,可以看到通过字段的查询获取到音频的详细信息。

2、MediaStore.Images

在该类中有一个借口和两个class ,分别为:

MediaStore.Images.ImageColumns可以查看图片的字段信息

MediaStore.Images.Media可以获取图片的相关信息

MediaStore.Images.Thumbnails可以获取图片的缩略图

关于MediaStore.Images.ImageColumns 可以查看api ,下面通过MediaStore.Images.Media 查询手机上的图片。
[java] view plain copy

private Uri imageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;  

通过上面查看字段的代码,可以看到如下图片的字段信息:

06-24 13:52:34.018: I/System.out(4755): 0 = _id
06-24 13:52:34.018: I/System.out(4755): 1 = _data
06-24 13:52:34.018: I/System.out(4755): 2 = _size
06-24 13:52:34.018: I/System.out(4755): 3 = _display_name
06-24 13:52:34.018: I/System.out(4755): 4 = mime_type
06-24 13:52:34.018: I/System.out(4755): 5 = title
06-24 13:52:34.018: I/System.out(4755): 6 = date_added
06-24 13:52:34.018: I/System.out(4755): 7 = date_modified
06-24 13:52:34.018: I/System.out(4755): 8 = description
06-24 13:52:34.018: I/System.out(4755): 9 = picasa_id
06-24 13:52:34.018: I/System.out(4755): 10 = isprivate
06-24 13:52:34.018: I/System.out(4755): 11 = latitude
06-24 13:52:34.018: I/System.out(4755): 12 = longitude
06-24 13:52:34.018: I/System.out(4755): 13 = datetaken
06-24 13:52:34.018: I/System.out(4755): 14 = orientation
06-24 13:52:34.018: I/System.out(4755): 15 = mini_thumb_magic
06-24 13:52:34.018: I/System.out(4755): 16 = bucket_id
06-24 13:52:34.018: I/System.out(4755): 17 = bucket_display_name
06-24 13:52:34.018: I/System.out(4755): 18 = is_drm
06-24 13:52:34.018: I/System.out(4755): 19 = drm_content_uri
06-24 13:52:34.018: I/System.out(4755): 20 = drm_offset
06-24 13:52:34.018: I/System.out(4755): 21 = drm_dataLen
06-24 13:52:34.018: I/System.out(4755): 22 = drm_rights_issuer
06-24 13:52:34.018: I/System.out(4755): 23 = drm_content_name
06-24 13:52:34.018: I/System.out(4755): 24 = drm_content_description
06-24 13:52:34.018: I/System.out(4755): 25 = drm_content_vendor
06-24 13:52:34.019: I/System.out(4755): 26 = drm_icon_uri
06-24 13:52:34.019: I/System.out(4755): 27 = drm_method

可以查看和音频的字段是有些不同的。获取图片的基本信息:
[java] view plain copy

 private void getUriData(Uri uri)  

    String[] projection = "_data","_display_name","_size","mime_type","title","orientation";  
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);  
    cursor.moveToFirst();  
    do   
System.out.println("_data = "+cursor.getString(cursor.getColumnIndex("_data")));  
System.out.println("_display_name = "+cursor.getString(cursor.getColumnIndex("_display_name")));  
System.out.println("_size = "+cursor.getString(cursor.getColumnIndex("_size")));  
System.out.println("mime_type = "+cursor.getString(cursor.getColumnIndex("mime_type")));  
System.out.println("title = "+cursor.getString(cursor.getColumnIndex("title")));  
System.out.println("orientation = "+cursor.getString(cursor.getColumnIndex("orientation")));  
 while (cursor.moveToNext());  
 <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>  

orientation 为图片的对其方式, 输出信息为:

06-24 13:57:59.653: I/System.out(4851): _data = /mnt/sdcard/sdcard2/Photo/IMG_20100101_081333.jpg
06-24 13:57:59.653: I/System.out(4851): _display_name = IMG_20100101_081333.jpg
06-24 13:57:59.653: I/System.out(4851): _size = 795457
06-24 13:57:59.653: I/System.out(4851): mime_type = image/jpeg
06-24 13:57:59.653: I/System.out(4851): title = IMG_20100101_081333
06-24 13:57:59.654: I/System.out(4851): orientation = 90

06-24 13:57:59.654: I/System.out(4851): _data = /mnt/sdcard/sdcard2/Photo/IMG_20100101_081344.jpg
06-24 13:57:59.654: I/System.out(4851): _display_name = IMG_20100101_081344.jpg
06-24 13:57:59.654: I/System.out(4851): _size = 673729
06-24 13:57:59.654: I/System.out(4851): mime_type = image/jpeg
06-24 13:57:59.654: I/System.out(4851): title = IMG_20100101_081344
06-24 13:57:59.654: I/System.out(4851): orientation = 90

06-24 13:57:59.654: I/System.out(4851): _data = /mnt/sdcard/QQ_Screenshot/1425453607656.png
06-24 13:57:59.654: I/System.out(4851): _display_name = 1425453607656.png
06-24 13:57:59.654: I/System.out(4851): _size = 65742
06-24 13:57:59.654: I/System.out(4851): mime_type = image/png
06-24 13:57:59.654: I/System.out(4851): title = 1425453607656
06-24 13:57:59.654: I/System.out(4851): orientation = null

MediaStore.Images.Thumbnails获取缩略图这个类和下面获取手机视频信息一起讲。

2、MediaStore.Video

该类有两个class比较常用:MediaStore.Video.Media MediaStore.Video.Thumbnails 一个是获取视频的相关信息,一个是获取视频的缩略图

MediaStore.Video.Media 用法和上面介绍的一样,不清楚它有什么字段的,可以先查询出来,再来获取视频的相关信息,和路径、名称、类型等等,这里就不介绍了。下面是获取视频的缩略图的相关操作。

MediaStore.Video.Thumbnails 主要用到这个两个方法:
[java] view plain copy

static Bitmap  getThumbnail(ContentResolver cr, long origId, long groupId, int kind, BitmapFactory.Options options)    

[java] view plain copy

static Bitmap  getThumbnail(ContentResolver cr, long origId, int kind, BitmapFactory.Options options)    

这里第一个参数可以通过 getContentResolver() 来获取 、第二个参数 origId 为视频的ID ,第三个参数 groupId 我也不太清楚,大家知道的可以告诉我一下O(∩_∩)O, 第四个参数kind 有两种类型分别为:
MICRO_KIND(微型分辨率小)MINI_KIND (迷你型)、第五个参数 为BitmapFactory.Option对象

<1> 第一种是使用上面介绍的方法:
[java] view plain copy

public class ThumbnailActivity extends Activity   

    private ListView listView;  

    private Uri videoUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;  

    @Override  
    protected void onCreate(Bundle savedInstanceState)   
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.video_listview);  

        listView = (ListView) findViewById(R.id.mylistview1);  
        new MyThumbnailAsyncTask().execute(videoUri);  

      

    /** 
     * 异步加载 
     * 
     */  
    private class MyThumbnailAsyncTask extends AsyncTask<Uri, Void, List<Bitmap>>  

        @Override  
        protected List<Bitmap> doInBackground(Uri... params)   
            // TODO Auto-generated method stub  
            List<Bitmap> data = getBitmapFromVideo(params[0]);  
            return data;  
          

        @Override  
        protected void onPostExecute(List<Bitmap> result)   
            listView.setAdapter(new MyThumbnailAdapter(result));  
            super.onPostExecute(result);  
          
      

    /** 
     * 获取手机上视频的缩略图 
     * @param uri 视频的Uri 
     * @return 
     */  
    private List<Bitmap> getBitmapFromVideo(Uri uri)  

        List<Bitmap> list = new ArrayList<Bitmap>();  
        ContentResolver cr = getContentResolver();  
        Cursor cursor = cr.query(uri, new String[]Media._ID, null, null, null);  
        cursor.moveToFirst();  
        do   
            long id = cursor.getLong(0); // 取得视频的ID,因为我上行只有一个参数所以下标为0  
            BitmapFactory.Options options = new Options();  
            Bitmap bitmap = MediaStore.Video.Thumbnails.getThumbnail(cr, id, MediaStore.Video.Thumbnails.MINI_KIND, options);  
            if (bitmap == null)   
                Log.e("TAG", "bitmap == null");  
              
            list.add(bitmap);  
         while (cursor.moveToNext());  

        return list;  
      

    private class MyThumbnailAdapter extends BaseAdapter  

        private List<Bitmap> mlist;  


        public MyThumbnailAdapter(List<Bitmap> list)   
            this.mlist = list;  
          

        @Override  
        public int getCount()   
            // TODO Auto-generated method stub  
            return mlist.size();  
          

        @Override  
        public Object getItem(int position)   
            // TODO Auto-generated method stub  
            return mlist.get(position);  
          

        @Override  
        public long getItemId(int position)   
            // TODO Auto-generated method stub  
            return position;  
          

        @Override  
        public View getView(int position, View convertView, ViewGroup parent)   

            ViewHolder holder  = null;  

            if (convertView == null)   
                holder = new ViewHolder();  
                convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.video_img, null);  
                holder.imageView = (ImageView) convertView.findViewById(R.id.my_img);  
                convertView.setTag(holder);  
            else  
                holder = (ViewHolder) convertView.getTag();  
              
            holder.imageView.setImageBitmap(mlist.get(position));  
            return convertView;  
          

        private class ViewHolder  
            private ImageView imageView;  
          
      

  

很简单XML就不贴了,就一个ListView。通过上面的方法图片缩略图的获取也是一样。

<2> 第二种通过 MediaMetadataRetriever 来获取:
[java] view plain copy

public class MediaMetadataActivity extends Activity  

    private ProgressDialog dialog = null;  
    private Uri videoUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;  
    private ListView listView;  

    @Override  
    protected void onCreate(Bundle savedInstanceState)   
        // TODO Auto-generated method stub  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.list_view);  

        listView = (ListView) findViewById(R.id.mylistview);  
        dialog = new ProgressDialog(this);  
        dialog.setMessage("加载数据中...");  
        dialog.show();  
        new myAsyncTask().execute(videoUri);  
      

    private class myAsyncTask extends AsyncTask<Uri, Void,List<ListItem> >  

        @Override  
        protected List<ListItem> doInBackground(Uri... params)   
            // TODO Auto-generated method stub  
            List<VideoItem> videoItems = getMediaPath(params[0]);  
            List<ListItem> items = getListItem(videoItems);  
            return items;  
          

        @Override  
        protected void onPostExecute(List<ListItem> result)   
            // TODO Auto-generated method stub  
            if (dialog!=null)   
                dialog.dismiss();  
              
            listView.setAdapter(new MyAdapter(result));  
            super.onPostExecute(result);  
          
      

    private List<ListItem> getListItem(List<VideoItem> items)  

        List<ListItem> listItems = new ArrayList<ListItem>();  
        for (int i = 0; i < items.size(); i++)   

            ListItem item = new ListItem();  
            item.setBitmap(getThumbnail(items.get(i).getPath()));  
            item.setTitle(items.get(i).getTitle());  
            listItems.add(item);  
          

        return listItems;  
      

    /** 
     * 主要是这个方法通过为MediaMetadataRetriever 设置视频的路径来取得缩略图 
     * @param path 视频的路径 
     * @return 
     */  
    private Bitmap getThumbnail(String path)  

        MediaMetadataRetriever retriever = new MediaMetadataRetriever();  
        retriever.setDataSource(path);  
        Bitmap bitmap = retriever.getFrameAtTime();  
        retriever.release();  
        return bitmap;  
      

    private List<VideoItem> getMediaPath(Uri uri)  

        List<VideoItem> mylist = new ArrayList<VideoItem>();  
        String projection[] = Media.DATA,Media.TITLE,Media.DURATION;  
        Cursor cursor  = getContentResolver().query(uri, projection, null, null, null);  
        cursor.moveToFirst();  
        int count = cursor.getCount();  
        for (int i = 0; i < count; i++)   

            VideoItem item = new VideoItem();  
            item.setPath(cursor.getString(0));  
            item.setTitle(cursor.getString(1));  
            mylist.add(item);  
            cursor.moveToNext();  
          
        return mylist;  
      

    private class MyAdapter extends BaseAdapter  

        List<ListItem> mlist;  

        public MyAdapter(List<ListItem> list)   
            super();  
            this.mlist = list;  
          

        @Override  
        public int getCount()   
            // TODO Auto-generated method stub  
            return mlist.size();  
          

        @Override  
        public Object getItem(int position)   
            // TODO Auto-generated method stub  
            return mlist.get(position);  
          

        @Override  
        public long getItemId(int position)   
            // TODO Auto-generated method stub  
            return position;  
          

        @Override  
        public View getView(int position, View convertView, ViewGroup parent)   
            ViewHolder holder  = null;  

            if (convertView == null)   
                holder = new ViewHolder();  
                convertView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.item, null);  
                holder.imageView = (ImageView) convertView.findViewById(R.id.img);  
                holder.textView = (TextView) convertView.findViewById(R.id.tv);  
                convertView.setTag(holder);  
            else  
                holder = (ViewHolder) convertView.getTag();  
              
            holder.imageView.setImageBitmap(mlist.get(position).getBitmap());  
            holder.textView.setText(mlist.get(position).getTitle());  
            return convertView;  
          

        private class ViewHolder  
            private ImageView imageView;  
            private TextView textView;  
          
      
  

MediaMetadataRetriever 除了通过 getFrameAtTime() 方法获取外,还可以用getFrameAtTime(long timeUs)和getFrameAtTime(long timeUs, int option)方法通过时长来获取,这就是获取视频缩略图的两种方式。

以上是关于Android之MediaStore的主要内容,如果未能解决你的问题,请参考以下文章

MediaStore 与Media.EXTERNAL_CONTENT_URI

ContentProvider之通过ContentResolver获取图像视频音频举例

ContentProvider之通过ContentResolver获取图像视频音频举例

Android开发之获取本地视频和获取自拍视频

Android:通过 MTP 连接时如何检测 MediaStore 的变化

Android 文件管理分区存储 ( MediaStore 文件操作 )