Android中利用ContentResolver获取本地音乐和相片
2014-01-13 08:54
267 查看
在Android中,例如图库和音乐播放器,它们能够扫描我们的系统,获取到本地的相片跟音乐,这一点是如何做到的呢?
当我们往手机上放图片或者音乐的时候,会在手机内存中某个位置上的某个database中存放图片或者音乐的信息,而我们的应用程序是能够通过ContentResolver去读取到这些数据的。
下面可以先看一下database在哪,如下:
然后在data/data/下面呢,有很多provider提供的数据库,而我们的音乐或者图片就是在一个叫做Media的库下:
external是智能手机中内置的SD卡,而internal则是机身的内存。
这两个database里面的结构是一样的,我们把external给拉到本地电脑上,如下红色框框显示的,左边就是从手机SD卡拉到电脑,右边是从电脑推到手机SD卡上。
接下来可以利用SQLiteSpy之类的工具打开我们的数据库,可以看到Images 和 Audio 相关的表和视图:
比如图片,我们可以查看images这张表,其结构如下:
音乐,可以查看audio的视图,如下:
既然知道了这些表的数据结构,那么如何在我们的应用程序中去获取到这些数据呢?答案,当然就是利用ContentResolver了。
具体看代码,下面我写的一个MusicLoader,是为了获取本地音乐,其中利用了一些过滤条件,只拿出我想要的音乐。
package com.example.nature;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.MediaStore.Audio.Media;
import android.util.Log;
public class MusicLoader {
private static final String TAG = "com.example.nature.MusicLoader";
private static List<MusicInfo> musicList = new ArrayList<MusicInfo>();
private static MusicLoader musicLoader;
private static ContentResolver contentResolver;
//Uri,指向external的database
private Uri contentUri = Media.EXTERNAL_CONTENT_URI;
//projection:选择的列; where:过滤条件; sortOrder:排序。
private String[] projection = {
Media._ID,
Media.DISPLAY_NAME,
Media.DATA,
Media.ALBUM,
Media.ARTIST,
Media.DURATION,
Media.SIZE
};
private String where = "mime_type in ('audio/mpeg','audio/x-ms-wma') and bucket_display_name <> 'audio' and is_music > 0 " ;
private String sortOrder = Media.DATA;
public static MusicLoader instance(ContentResolver pContentResolver){
if(musicLoader == null){
contentResolver = pContentResolver;
musicLoader = new MusicLoader();
}
return musicLoader;
}
private MusicLoader(){ //利用ContentResolver的query函数来查询数据,然后将得到的结果放到MusicInfo对象中,最后放到数组中
Cursor cursor = contentResolver.query(contentUri, projection, where, null, sortOrder);
if(cursor == null){
Log.v(TAG,"Line(37 ) Music Loader cursor == null.");
}else if(!cursor.moveToFirst()){
Log.v(TAG,"Line(39 ) Music Loader cursor.moveToFirst() returns false.");
}else{
int displayNameCol = cursor.getColumnIndex(Media.DISPLAY_NAME);
int albumCol = cursor.getColumnIndex(Media.ALBUM);
int idCol = cursor.getColumnIndex(Media._ID);
int durationCol = cursor.getColumnIndex(Media.DURATION);
int sizeCol = cursor.getColumnIndex(Media.SIZE);
int artistCol = cursor.getColumnIndex(Media.ARTIST);
int urlCol = cursor.getColumnIndex(Media.DATA);
do{
String title = cursor.getString(displayNameCol);
String album = cursor.getString(albumCol);
long id = cursor.getLong(idCol);
int duration = cursor.getInt(durationCol);
long size = cursor.getLong(sizeCol);
String artist = cursor.getString(artistCol);
String url = cursor.getString(urlCol);
MusicInfo musicInfo = new MusicInfo(id, title);
musicInfo.setAlbum(album);
musicInfo.setDuration(duration);
musicInfo.setSize(size);
musicInfo.setArtist(artist);
musicInfo.setUrl(url);
musicList.add(musicInfo);
}while(cursor.moveToNext());
}
}
public List<MusicInfo> getMusicList(){
return musicList;
}
public Uri getMusicUriById(long id){
Uri uri = ContentUris.withAppendedId(contentUri, id);
return uri;
}
//下面是自定义的一个MusicInfo子类,实现了Parcelable,为的是可以将整个MusicInfo的ArrayList在Activity和Service中传送,=_=!!,但其实不用
static class MusicInfo implements Parcelable{
private long id;
private String title;
private String album;
private int duration;
private long size;
private String artist;
private String url;
public MusicInfo(){
}
public MusicInfo(long pId, String pTitle){
id = pId;
title = pTitle;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAlbum() {
return album;
}
public void setAlbum(String album) {
this.album = album;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeString(title);
dest.writeString(album);
dest.writeString(artist);
dest.writeString(url);
dest.writeInt(duration);
dest.writeLong(size);
}
public static final Parcelable.Creator<MusicInfo>
CREATOR = new Creator<MusicLoader.MusicInfo>() {
@Override
public MusicInfo[] newArray(int size) {
return new MusicInfo[size];
}
@Override
public MusicInfo createFromParcel(Parcel source) {
MusicInfo musicInfo = new MusicInfo();
musicInfo.setId(source.readLong());
musicInfo.setTitle(source.readString());
musicInfo.setAlbum(source.readString());
musicInfo.setArtist(source.readString());
musicInfo.setUrl(source.readString());
musicInfo.setDuration(source.readInt());
musicInfo.setSize(source.readLong());
return musicInfo;
}
};
}
}
最后,我们就可以在我们的手机上看到我们音乐了,不过数据库中有些是乱码的,我还不知道怎么解决。。。
图片的获取也是相类似的,放上代码,具体的自行琢磨:
package com.example.hmgallery;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentResolver;
import android.database.Cursor;
import android.provider.MediaStore.Images.Media;
import android.provider.MediaStore.Images.Thumbnails;
import android.util.SparseArray;
public class Images{
public static final String IMAGE_PATH = "IMAGE_PATH";
public static final String IMAGE_ID = "IMAGE_ID";
public static final String IMAGE_POSITION = "IMAGE_POSITION";
public static final String IMAGE_COUNTS = "IMAGE_COUNTS";
private static List<ImageItem> imageItems = new ArrayList<ImageItem>();
private static SparseArray<ImageItem> tempArray;
public static void loadImages(ContentResolver contentResolver){
tempArray = new SparseArray<ImageItem>();
String[] projection = {Media._ID,Media.DATA,Media.ORIENTATION};
String where = Media.BUCKET_DISPLAY_NAME + " = 'Camera'";
String sortOrder = Media._ID + " desc";
StringBuilder inImageIds = new StringBuilder(Thumbnails.IMAGE_ID);
inImageIds.append(" in ( ");
Cursor cursor = contentResolver.query(Media.EXTERNAL_CONTENT_URI, projection, where, null, sortOrder);
if(cursor.moveToFirst()){
do {
int imageId = cursor.getInt(cursor.getColumnIndex(Media._ID));
String imagePath = cursor.getString(cursor.getColumnIndex(Media.DATA));
int orientation = cursor.getInt(cursor.getColumnIndex(Media.ORIENTATION));
ImageItem imageItem = new ImageItem(imageId,imagePath,orientation);
imageItems.add(imageItem);
tempArray.put(imageId, imageItem);
inImageIds.append(imageId).append(",");
}while(cursor.moveToNext());
}
inImageIds.deleteCharAt(inImageIds.length() - 1);
inImageIds.append(" ) ");
String[] thumbnailProjection = {Thumbnails.DATA,Thumbnails.IMAGE_ID};
cursor = contentResolver.query(Thumbnails.EXTERNAL_CONTENT_URI, thumbnailProjection, inImageIds.toString(), null, null);
if(cursor.moveToFirst()){
do {
int imageId = cursor.getInt(cursor.getColumnIndex(Thumbnails.IMAGE_ID));
String thumnbailPath = cursor.getString(cursor.getColumnIndex(Media.DATA));
ImageItem imageItem = tempArray.get(imageId);
if(imageItem != null){
imageItem.setThumbnailPath(thumnbailPath);
}
}while(cursor.moveToNext());
}
tempArray = null;
}
public static ImageItem[] getImageItems(){
return imageItems.toArray(new ImageItem[]{});
}
}
当我们往手机上放图片或者音乐的时候,会在手机内存中某个位置上的某个database中存放图片或者音乐的信息,而我们的应用程序是能够通过ContentResolver去读取到这些数据的。
下面可以先看一下database在哪,如下:
然后在data/data/下面呢,有很多provider提供的数据库,而我们的音乐或者图片就是在一个叫做Media的库下:
external是智能手机中内置的SD卡,而internal则是机身的内存。
这两个database里面的结构是一样的,我们把external给拉到本地电脑上,如下红色框框显示的,左边就是从手机SD卡拉到电脑,右边是从电脑推到手机SD卡上。
接下来可以利用SQLiteSpy之类的工具打开我们的数据库,可以看到Images 和 Audio 相关的表和视图:
比如图片,我们可以查看images这张表,其结构如下:
音乐,可以查看audio的视图,如下:
既然知道了这些表的数据结构,那么如何在我们的应用程序中去获取到这些数据呢?答案,当然就是利用ContentResolver了。
具体看代码,下面我写的一个MusicLoader,是为了获取本地音乐,其中利用了一些过滤条件,只拿出我想要的音乐。
package com.example.nature;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.MediaStore.Audio.Media;
import android.util.Log;
public class MusicLoader {
private static final String TAG = "com.example.nature.MusicLoader";
private static List<MusicInfo> musicList = new ArrayList<MusicInfo>();
private static MusicLoader musicLoader;
private static ContentResolver contentResolver;
//Uri,指向external的database
private Uri contentUri = Media.EXTERNAL_CONTENT_URI;
//projection:选择的列; where:过滤条件; sortOrder:排序。
private String[] projection = {
Media._ID,
Media.DISPLAY_NAME,
Media.DATA,
Media.ALBUM,
Media.ARTIST,
Media.DURATION,
Media.SIZE
};
private String where = "mime_type in ('audio/mpeg','audio/x-ms-wma') and bucket_display_name <> 'audio' and is_music > 0 " ;
private String sortOrder = Media.DATA;
public static MusicLoader instance(ContentResolver pContentResolver){
if(musicLoader == null){
contentResolver = pContentResolver;
musicLoader = new MusicLoader();
}
return musicLoader;
}
private MusicLoader(){ //利用ContentResolver的query函数来查询数据,然后将得到的结果放到MusicInfo对象中,最后放到数组中
Cursor cursor = contentResolver.query(contentUri, projection, where, null, sortOrder);
if(cursor == null){
Log.v(TAG,"Line(37 ) Music Loader cursor == null.");
}else if(!cursor.moveToFirst()){
Log.v(TAG,"Line(39 ) Music Loader cursor.moveToFirst() returns false.");
}else{
int displayNameCol = cursor.getColumnIndex(Media.DISPLAY_NAME);
int albumCol = cursor.getColumnIndex(Media.ALBUM);
int idCol = cursor.getColumnIndex(Media._ID);
int durationCol = cursor.getColumnIndex(Media.DURATION);
int sizeCol = cursor.getColumnIndex(Media.SIZE);
int artistCol = cursor.getColumnIndex(Media.ARTIST);
int urlCol = cursor.getColumnIndex(Media.DATA);
do{
String title = cursor.getString(displayNameCol);
String album = cursor.getString(albumCol);
long id = cursor.getLong(idCol);
int duration = cursor.getInt(durationCol);
long size = cursor.getLong(sizeCol);
String artist = cursor.getString(artistCol);
String url = cursor.getString(urlCol);
MusicInfo musicInfo = new MusicInfo(id, title);
musicInfo.setAlbum(album);
musicInfo.setDuration(duration);
musicInfo.setSize(size);
musicInfo.setArtist(artist);
musicInfo.setUrl(url);
musicList.add(musicInfo);
}while(cursor.moveToNext());
}
}
public List<MusicInfo> getMusicList(){
return musicList;
}
public Uri getMusicUriById(long id){
Uri uri = ContentUris.withAppendedId(contentUri, id);
return uri;
}
//下面是自定义的一个MusicInfo子类,实现了Parcelable,为的是可以将整个MusicInfo的ArrayList在Activity和Service中传送,=_=!!,但其实不用
static class MusicInfo implements Parcelable{
private long id;
private String title;
private String album;
private int duration;
private long size;
private String artist;
private String url;
public MusicInfo(){
}
public MusicInfo(long pId, String pTitle){
id = pId;
title = pTitle;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAlbum() {
return album;
}
public void setAlbum(String album) {
this.album = album;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeString(title);
dest.writeString(album);
dest.writeString(artist);
dest.writeString(url);
dest.writeInt(duration);
dest.writeLong(size);
}
public static final Parcelable.Creator<MusicInfo>
CREATOR = new Creator<MusicLoader.MusicInfo>() {
@Override
public MusicInfo[] newArray(int size) {
return new MusicInfo[size];
}
@Override
public MusicInfo createFromParcel(Parcel source) {
MusicInfo musicInfo = new MusicInfo();
musicInfo.setId(source.readLong());
musicInfo.setTitle(source.readString());
musicInfo.setAlbum(source.readString());
musicInfo.setArtist(source.readString());
musicInfo.setUrl(source.readString());
musicInfo.setDuration(source.readInt());
musicInfo.setSize(source.readLong());
return musicInfo;
}
};
}
}
最后,我们就可以在我们的手机上看到我们音乐了,不过数据库中有些是乱码的,我还不知道怎么解决。。。
图片的获取也是相类似的,放上代码,具体的自行琢磨:
package com.example.hmgallery;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentResolver;
import android.database.Cursor;
import android.provider.MediaStore.Images.Media;
import android.provider.MediaStore.Images.Thumbnails;
import android.util.SparseArray;
public class Images{
public static final String IMAGE_PATH = "IMAGE_PATH";
public static final String IMAGE_ID = "IMAGE_ID";
public static final String IMAGE_POSITION = "IMAGE_POSITION";
public static final String IMAGE_COUNTS = "IMAGE_COUNTS";
private static List<ImageItem> imageItems = new ArrayList<ImageItem>();
private static SparseArray<ImageItem> tempArray;
public static void loadImages(ContentResolver contentResolver){
tempArray = new SparseArray<ImageItem>();
String[] projection = {Media._ID,Media.DATA,Media.ORIENTATION};
String where = Media.BUCKET_DISPLAY_NAME + " = 'Camera'";
String sortOrder = Media._ID + " desc";
StringBuilder inImageIds = new StringBuilder(Thumbnails.IMAGE_ID);
inImageIds.append(" in ( ");
Cursor cursor = contentResolver.query(Media.EXTERNAL_CONTENT_URI, projection, where, null, sortOrder);
if(cursor.moveToFirst()){
do {
int imageId = cursor.getInt(cursor.getColumnIndex(Media._ID));
String imagePath = cursor.getString(cursor.getColumnIndex(Media.DATA));
int orientation = cursor.getInt(cursor.getColumnIndex(Media.ORIENTATION));
ImageItem imageItem = new ImageItem(imageId,imagePath,orientation);
imageItems.add(imageItem);
tempArray.put(imageId, imageItem);
inImageIds.append(imageId).append(",");
}while(cursor.moveToNext());
}
inImageIds.deleteCharAt(inImageIds.length() - 1);
inImageIds.append(" ) ");
String[] thumbnailProjection = {Thumbnails.DATA,Thumbnails.IMAGE_ID};
cursor = contentResolver.query(Thumbnails.EXTERNAL_CONTENT_URI, thumbnailProjection, inImageIds.toString(), null, null);
if(cursor.moveToFirst()){
do {
int imageId = cursor.getInt(cursor.getColumnIndex(Thumbnails.IMAGE_ID));
String thumnbailPath = cursor.getString(cursor.getColumnIndex(Media.DATA));
ImageItem imageItem = tempArray.get(imageId);
if(imageItem != null){
imageItem.setThumbnailPath(thumnbailPath);
}
}while(cursor.moveToNext());
}
tempArray = null;
}
public static ImageItem[] getImageItems(){
return imageItems.toArray(new ImageItem[]{});
}
}
相关文章推荐
- Android中利用ContentResolver获取本地音乐和相片
- Android中利用ContentResolver获取本地音乐和相片
- Android中利用ContentResolver获取本地音乐和相片
- android, 删除SD卡音乐文件。通过getContentResolver读取音乐文件,可以获取到一个完整的路径,直接new File(这括号写获取的路径).delete();
- 【android】利用ContentObserver监听短信来获取验证码
- Android ContentResolver ContactsContract 获取手机联系人信息
- Android构造音乐播放器并实现获取本地音乐
- Android ContentResolver CallLog 获取手机通话记录
- Android 音乐播放器的开发教程(五)本地音乐的获取及显示 ----- 小达
- android获取本地音乐的专辑图片
- android获取本地音乐的专辑的图片
- Android获取本地图片之ACTION_GET_CONTENT与ACTION_PICK区别
- Android仿虾米音乐播放器之本地音乐获取
- Android利用极光推送获取到消息并缓存至本地
- android网络获取图片并保存在本地和获取手机SD卡中的图片显示到ImageView上及利用代码删除图片
- android获取本地音乐的专辑的图片
- Android 4.4以上获取图片URI格式不同导致getContentResolver返回null
- 本地音乐播放器MediaPlayer获取所有歌曲信息,getContentResolver()
- Android利用ContentProvider获取本地数据的方法
- android 的视频的缩略图以及在android上的本地图片和本地音乐的查询