1.概述
在Andorid系統中所有的文件路徑都保存在一個數據庫中,位於data/data/com.android.providers.media文件夾下的external.db
裏面的files表就有我們需要的內容,這個表包含了機器所有的文件。接下來只要選擇合適的sql語句來獲取我們需要的內容就行了。
2.實現
數據庫結構如下圖
首先過濾出相冊文件夾,獲取所在文件夾路徑,文件夾名稱,文件夾文件數目,文件路徑和修改時間。構建文件夾和封面
public static Cursor getAlbumCursor(ContentResolver cr){
//打開files這個表
Uri uri= MediaStore.Files.getContentUri("external");
String [] project =new String[]{
MediaStore.Files.FileColumns.PARENT,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
"count(*)",
MediaStore.Images.Media.DATA,
"max(" + MediaStore.Images.Media.DATE_MODIFIED + ")"
};
//用group by進行整合
String selection = String.format("%s=? or %s=?) group by (%s",
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.Files.FileColumns.PARENT
) ;
String[] selectionArgs = new String[]{
MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE+"",//獲取圖片文件
MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO+"",//獲取視頻文件
};
String sortOrder = MediaStore.Images.Media.DATE_MODIFIED + " desc";
// String sortOrder = "max(date_modified) DESC";
// 轉換成sql語句: SELECT parent, bucket_display_name, count(*), _data, max(date_modified) FROM files WHERE (media_type=? or media_type=?)
// group by (parent) HAVING (_data NOT LIKE ? ) ORDER BY max(date_modified) DESC
return cr.query(uri,project,selection,selectionArgs,sortOrder);
}
拿到cursor後就可以進行查詢獲取數據
public Album(Cursor cur) {
//圖片路徑
this(cur.getString(3),
//所在文件夾的名稱
cur.getString(1),
//所在的父文件
cur.getLong(0),
//文件夾的文件數目
cur.getInt(2),
//修改時間
cur.getLong(4)
);
}
相冊文件夾構建好了後,在來獲取文件夾裏面的所有的圖片
public static Cursor getMediaCursor(ContentResolver cr,Album album){
Uri uri = MediaStore.Files.getContentUri("external");
String[] sProjection = new String[] {
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DATE_TAKEN,
MediaStore.Images.Media.MIME_TYPE,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media.ORIENTATION
};
//獲取parent一樣的文件
String selections = (String.format("(%s=? or %s=?) and %s=?",
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.Files.FileColumns.PARENT));
String[] selectionArgs = new String[]{
MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE+"",
MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO+"",
album.getId()+""
};
String sortOrder = MediaStore.Images.Media.DATE_MODIFIED + " desc";
return cr.query(uri,sProjection,selections,selectionArgs,sortOrder);
}
接下來構建實體類
public Media(Cursor cur) {
//具體路徑
this(cur.getString(0),
cur.getLong(1),
cur.getString(2),
cur.getLong(3),
cur.getInt(4));
}
這種方式主要是利用好了sql語句,同時結合rxjava的話可以實現查詢一張照片顯示一張照片的效果。
3.擴展
類似的還可以獲取特定類型的文件
private ArrayList<LayoutElementParcelable> listImages() {
ArrayList<LayoutElementParcelable> images = new ArrayList<>();
final String[] projection = {MediaStore.Images.Media.DATA};
final Cursor cursor = c.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection, null, null, null);
if (cursor == null)
return images;
else if (cursor.getCount() > 0 && cursor.moveToFirst()) {
do {
String path = cursor.getString(cursor.getColumnIndex
(MediaStore.Files.FileColumns.DATA));
HybridFileParcelable strings = RootHelper.generateBaseFile(new File(path), showHiddenFiles);
if (strings != null) {
LayoutElementParcelable parcelable = createListParcelables(strings);
if(parcelable != null) images.add(parcelable);
}
} while (cursor.moveToNext());
}
cursor.close();
return images;
}
private ArrayList<LayoutElementParcelable> listVideos() {
ArrayList<LayoutElementParcelable> videos = new ArrayList<>();
final String[] projection = {MediaStore.Images.Media.DATA};
final Cursor cursor = c.getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection, null, null, null);
if (cursor == null)
return videos;
else if (cursor.getCount() > 0 && cursor.moveToFirst()) {
do {
String path = cursor.getString(cursor.getColumnIndex
(MediaStore.Files.FileColumns.DATA));
HybridFileParcelable strings = RootHelper.generateBaseFile(new File(path), showHiddenFiles);
if (strings != null) {
LayoutElementParcelable parcelable = createListParcelables(strings);
if(parcelable != null) videos.add(parcelable);
}
} while (cursor.moveToNext());
}
cursor.close();
return videos;
}
private ArrayList<LayoutElementParcelable> listaudio() {
String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
String[] projection = {
MediaStore.Audio.Media.DATA
};
Cursor cursor = c.getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
projection,
selection,
null,
null);
ArrayList<LayoutElementParcelable> songs = new ArrayList<>();
if (cursor == null)
return songs;
else if (cursor.getCount() > 0 && cursor.moveToFirst()) {
do {
String path = cursor.getString(cursor.getColumnIndex
(MediaStore.Files.FileColumns.DATA));
HybridFileParcelable strings = RootHelper.generateBaseFile(new File(path), showHiddenFiles);
if (strings != null) {
LayoutElementParcelable parcelable = createListParcelables(strings);
if(parcelable != null) songs.add(parcelable);
}
} while (cursor.moveToNext());
}
cursor.close();
return songs;
}
private ArrayList<LayoutElementParcelable> listDocs() {
ArrayList<LayoutElementParcelable> docs = new ArrayList<>();
final String[] projection = {MediaStore.Files.FileColumns.DATA};
Cursor cursor = c.getContentResolver().query(MediaStore.Files.getContentUri("external"),
projection, null, null, null);
String[] types = new String[]{".pdf", ".xml", ".html", ".asm", ".text/x-asm", ".def", ".in", ".rc",
".list", ".log", ".pl", ".prop", ".properties", ".rc",
".doc", ".docx", ".msg", ".odt", ".pages", ".rtf", ".txt", ".wpd", ".wps"};
if (cursor == null)
return docs;
else if (cursor.getCount() > 0 && cursor.moveToFirst()) {
do {
String path = cursor.getString(cursor.getColumnIndex
(MediaStore.Files.FileColumns.DATA));
if (path != null && Arrays.asList(types).contains(path)) {
HybridFileParcelable strings = RootHelper.generateBaseFile(new File(path), showHiddenFiles);
if (strings != null) {
LayoutElementParcelable parcelable = createListParcelables(strings);
if(parcelable != null) docs.add(parcelable);
}
}
} while (cursor.moveToNext());
}
cursor.close();
Collections.sort(docs, (lhs, rhs) -> -1 * Long.valueOf(lhs.date).compareTo(rhs.date));
if (docs.size() > 20)
for (int i = docs.size() - 1; i > 20; i--) {
docs.remove(i);
}
return docs;
}
private ArrayList<LayoutElementParcelable> listApks() {
ArrayList<LayoutElementParcelable> apks = new ArrayList<>();
final String[] projection = {MediaStore.Files.FileColumns.DATA};
Cursor cursor = c.getContentResolver()
.query(MediaStore.Files.getContentUri("external"), projection, null, null, null);
if (cursor == null)
return apks;
else if (cursor.getCount() > 0 && cursor.moveToFirst()) {
do {
String path = cursor.getString(cursor.getColumnIndex
(MediaStore.Files.FileColumns.DATA));
if (path != null && path.endsWith(".apk")) {
HybridFileParcelable strings = RootHelper.generateBaseFile(new File(path), showHiddenFiles);
if (strings != null) {
LayoutElementParcelable parcelable = createListParcelables(strings);
if(parcelable != null) apks.add(parcelable);
}
}
} while (cursor.moveToNext());
}
cursor.close();
return apks;
}