// MediaReadTask
public class MediaReadTask extends AsyncTask<Void, Void, MediaReadTask.ResultWrapper> {
public interface Callback {
/**
* Callback the results.
*
* @param albumFolders album folder list.
*/
void onScanCallback(ArrayList<AlbumFolder> albumFolders, ArrayList<AlbumFile> checkedFiles);
}
static class ResultWrapper {
private ArrayList<AlbumFolder> mAlbumFolders;
private ArrayList<AlbumFile> mAlbumFiles;
}
private int mFunction;
private List<AlbumFile> mCheckedFiles;
private MediaReader mMediaReader;
private Callback mCallback;
public MediaReadTask(int function, List<AlbumFile> checkedFiles, MediaReader mediaReader, Callback callback) {
this.mFunction = function;
this.mCheckedFiles = checkedFiles;
this.mMediaReader = mediaReader;
this.mCallback = callback;
}
@Override
protected ResultWrapper doInBackground(Void... params) {
ArrayList<AlbumFolder> albumFolders;
switch (mFunction) {
case AlbumConstant.FUNCTION_CHOICE_IMAGE: {
albumFolders = mMediaReader.getAllImage();
break;
}
case AlbumConstant.FUNCTION_CHOICE_VIDEO: {
albumFolders = mMediaReader.getAllVideo();
break;
}
case AlbumConstant.FUNCTION_CHOICE_ALBUM: {
albumFolders = mMediaReader.getAllMedia();
break;
}
default: {
throw new AssertionError("This should not be the case.");
}
}
ArrayList<AlbumFile> checkedFiles = new ArrayList<>();
if (mCheckedFiles != null && !mCheckedFiles.isEmpty()) {
List<AlbumFile> albumFiles = albumFolders.get(0).getAlbumFiles();
for (AlbumFile checkAlbumFile : mCheckedFiles) {
for (int i = 0; i < albumFiles.size(); i++) {
AlbumFile albumFile = albumFiles.get(i);
if (checkAlbumFile.equals(albumFile)) {
albumFile.setChecked(true);
checkedFiles.add(albumFile);
}
}
}
}
ResultWrapper wrapper = new ResultWrapper();
wrapper.mAlbumFolders = albumFolders;
wrapper.mAlbumFiles = checkedFiles;
return wrapper;
}
@Override
protected void onPostExecute(ResultWrapper wrapper) {
mCallback.onScanCallback(wrapper.mAlbumFolders, wrapper.mAlbumFiles);
}
}
public class MediaReader {
private Context mContext;
private Filter<Long> mSizeFilter;
private Filter<String> mMimeFilter;
private Filter<Long> mDurationFilter;
private boolean mFilterVisibility;
public MediaReader(Context context, Filter<Long> sizeFilter, Filter<String> mimeFilter, Filter<Long> durationFilter, boolean filterVisibility) {
this.mContext = context;
this.mSizeFilter = sizeFilter;
this.mMimeFilter = mimeFilter;
this.mDurationFilter = durationFilter;
this.mFilterVisibility = filterVisibility;
}
/**
* Image attribute.
*/
private static final String[] IMAGES = {
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.MIME_TYPE,
MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.Media.LATITUDE,
MediaStore.Images.Media.LONGITUDE,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media.DISPLAY_NAME
};
/**
* Scan for image files.
*/
@WorkerThread
private void scanImageFile(Map<String, AlbumFolder> albumFolderMap, AlbumFolder allFileFolder) {
ContentResolver contentResolver = mContext.getContentResolver();
Cursor cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
IMAGES,
null,
null,
null);
if (cursor != null) {
while (cursor.moveToNext()) {
String path = cursor.getString(0);
String bucketName = cursor.getString(1);
String mimeType = cursor.getString(2);
long addDate = cursor.getLong(3);
float latitude = cursor.getFloat(4);
float longitude = cursor.getFloat(5);
long size = cursor.getLong(6);
String fileName = cursor.getString(7);
AlbumFile imageFile = new AlbumFile();
imageFile.setMediaType(AlbumFile.TYPE_IMAGE);
imageFile.setPath(path);
imageFile.setFileName(fileName);
imageFile.setBucketName(bucketName);
imageFile.setMimeType(mimeType);
imageFile.setAddDate(addDate);
imageFile.setLatitude(latitude);
imageFile.setLongitude(longitude);
imageFile.setSize(size);
if (mSizeFilter != null && mSizeFilter.filter(size)) {
if (!mFilterVisibility) continue;
imageFile.setDisable(true);
}
if (mMimeFilter != null && mMimeFilter.filter(mimeType)) {
if (!mFilterVisibility) continue;
imageFile.setDisable(true);
}
allFileFolder.addAlbumFile(imageFile);
AlbumFolder albumFolder = albumFolderMap.get(bucketName);
if (albumFolder != null)
albumFolder.addAlbumFile(imageFile);
else {
albumFolder = new AlbumFolder();
albumFolder.setName(bucketName);
albumFolder.addAlbumFile(imageFile);
albumFolderMap.put(bucketName, albumFolder);
}
}
cursor.close();
}
}
/**
* Video attribute.
*/
private static final String[] VIDEOS = {
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media.MIME_TYPE,
MediaStore.Video.Media.DATE_ADDED,
MediaStore.Video.Media.LATITUDE,
MediaStore.Video.Media.LONGITUDE,
MediaStore.Video.Media.SIZE,
MediaStore.Video.Media.DURATION
};
/**
* Scan for image files.
*/
@WorkerThread
private void scanVideoFile(Map<String, AlbumFolder> albumFolderMap, AlbumFolder allFileFolder) {
ContentResolver contentResolver = mContext.getContentResolver();
Cursor cursor = contentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
VIDEOS,
null,
null,
null);
if (cursor != null) {
while (cursor.moveToNext()) {
String path = cursor.getString(0);
String bucketName = cursor.getString(1);
String mimeType = cursor.getString(2);
long addDate = cursor.getLong(3);
float latitude = cursor.getFloat(4);
float longitude = cursor.getFloat(5);
long size = cursor.getLong(6);
long duration = cursor.getLong(7);
AlbumFile videoFile = new AlbumFile();
videoFile.setMediaType(AlbumFile.TYPE_VIDEO);
videoFile.setPath(path);
videoFile.setBucketName(bucketName);
videoFile.setMimeType(mimeType);
videoFile.setAddDate(addDate);
videoFile.setLatitude(latitude);
videoFile.setLongitude(longitude);
videoFile.setSize(size);
videoFile.setDuration(duration);
if (mSizeFilter != null && mSizeFilter.filter(size)) {
if (!mFilterVisibility) continue;
videoFile.setDisable(true);
}
if (mMimeFilter != null && mMimeFilter.filter(mimeType)) {
if (!mFilterVisibility) continue;
videoFile.setDisable(true);
}
if (mDurationFilter != null && mDurationFilter.filter(duration)) {
if (!mFilterVisibility) continue;
videoFile.setDisable(true);
}
allFileFolder.addAlbumFile(videoFile);
AlbumFolder albumFolder = albumFolderMap.get(bucketName);
if (albumFolder != null)
albumFolder.addAlbumFile(videoFile);
else {
albumFolder = new AlbumFolder();
albumFolder.setName(bucketName);
albumFolder.addAlbumFile(videoFile);
albumFolderMap.put(bucketName, albumFolder);
}
}
cursor.close();
}
}
/**
* Scan the list of pictures in the library.
*/
@WorkerThread
public ArrayList<AlbumFolder> getAllImage() {
Map<String, AlbumFolder> albumFolderMap = new HashMap<>();
AlbumFolder allFileFolder = new AlbumFolder();
allFileFolder.setChecked(true);
allFileFolder.setName(mContext.getString(R.string.album_all_images));
scanImageFile(albumFolderMap, allFileFolder);
ArrayList<AlbumFolder> albumFolders = new ArrayList<>();
Collections.sort(allFileFolder.getAlbumFiles());
albumFolders.add(allFileFolder);
for (Map.Entry<String, AlbumFolder> folderEntry : albumFolderMap.entrySet()) {
AlbumFolder albumFolder = folderEntry.getValue();
Collections.sort(albumFolder.getAlbumFiles());
albumFolders.add(albumFolder);
}
return albumFolders;
}
/**
* Scan the list of videos in the library.
*/
@WorkerThread
public ArrayList<AlbumFolder> getAllVideo() {
Map<String, AlbumFolder> albumFolderMap = new HashMap<>();
AlbumFolder allFileFolder = new AlbumFolder();
allFileFolder.setChecked(true);
allFileFolder.setName(mContext.getString(R.string.album_all_videos));
scanVideoFile(albumFolderMap, allFileFolder);
ArrayList<AlbumFolder> albumFolders = new ArrayList<>();
Collections.sort(allFileFolder.getAlbumFiles());
albumFolders.add(allFileFolder);
for (Map.Entry<String, AlbumFolder> folderEntry : albumFolderMap.entrySet()) {
AlbumFolder albumFolder = folderEntry.getValue();
Collections.sort(albumFolder.getAlbumFiles());
albumFolders.add(albumFolder);
}
return albumFolders;
}
/**
* Get all the multimedia files, including videos and pictures.
*/
@WorkerThread
public ArrayList<AlbumFolder> getAllMedia() {
Map<String, AlbumFolder> albumFolderMap = new HashMap<>();
AlbumFolder allFileFolder = new AlbumFolder();
allFileFolder.setChecked(true);
allFileFolder.setName(mContext.getString(R.string.album_all_images_videos));
scanImageFile(albumFolderMap, allFileFolder);
scanVideoFile(albumFolderMap, allFileFolder);
ArrayList<AlbumFolder> albumFolders = new ArrayList<>();
Collections.sort(allFileFolder.getAlbumFiles());
albumFolders.add(allFileFolder);
for (Map.Entry<String, AlbumFolder> folderEntry : albumFolderMap.entrySet()) {
AlbumFolder albumFolder = folderEntry.getValue();
Collections.sort(albumFolder.getAlbumFiles());
albumFolders.add(albumFolder);
}
return albumFolders;
}
}
public class AlbumFolder implements Parcelable {
/**
* Folder name.
*/
private String name;
/**
* Image list in folder.
*/
private ArrayList<AlbumFile> mAlbumFiles = new ArrayList<>();
/**
* checked.
*/
private boolean isChecked;
public AlbumFolder() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<AlbumFile> getAlbumFiles() {
return mAlbumFiles;
}
public void addAlbumFile(AlbumFile albumFile) {
mAlbumFiles.add(albumFile);
}
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean checked) {
isChecked = checked;
}
protected AlbumFolder(Parcel in) {
name = in.readString();
mAlbumFiles = in.createTypedArrayList(AlbumFile.CREATOR);
isChecked = in.readByte() != 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeTypedList(mAlbumFiles);
dest.writeByte((byte) (isChecked ? 1 : 0));
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<AlbumFolder> CREATOR = new Creator<AlbumFolder>() {
@Override
public AlbumFolder createFromParcel(Parcel in) {
return new AlbumFolder(in);
}
@Override
public AlbumFolder[] newArray(int size) {
return new AlbumFolder[size];
}
};
}
public class AlbumFile implements Parcelable, Comparable<AlbumFile> {
public static final int TYPE_IMAGE = 1;
public static final int TYPE_VIDEO = 2;
public String getFileName() {
return mFileName;
}
public void setFileName(String fileName) {
this.mFileName = fileName;
}
@Retention(RetentionPolicy.SOURCE)
@IntDef({TYPE_IMAGE, TYPE_VIDEO})
public @interface MediaType {
}
/**
* File path.
*/
private String mPath;
/**
* File name.
*/
private String mFileName;
/**
* Folder mName.
*/
private String mBucketName;
/**
* File mime type.
*/
private String mMimeType;
/**
* Add date.
*/
private long mAddDate;
/**
* Latitude
*/
private float mLatitude;
/**
* Longitude.
*/
private float mLongitude;
/**
* Size.
*/
private long mSize;
/**
* Duration.
*/
private long mDuration;
/**
* Thumb path.
*/
private String mThumbPath;
/**
* MediaType.
*/
private int mMediaType;
/**
* Checked.
*/
private boolean isChecked;
/**
* Enabled.
*/
private boolean isDisable;
public AlbumFile() {
}
@Override
public int compareTo(AlbumFile o) {
long time = o.getAddDate() - getAddDate();
if (time > Integer.MAX_VALUE)
return Integer.MAX_VALUE;
else if (time < -Integer.MAX_VALUE)
return -Integer.MAX_VALUE;
return (int) time;
}
@Override
public boolean equals(Object obj) {
if (obj != null && obj instanceof AlbumFile) {
AlbumFile o = (AlbumFile) obj;
String inPath = o.getPath();
if (mPath != null && inPath != null) {
return mPath.equals(inPath);
}
}
return super.equals(obj);
}
@Override
public int hashCode() {
return mPath != null ? mPath.hashCode() : super.hashCode();
}
public String getPath() {
return mPath;
}
public void setPath(String path) {
mPath = path;
}
public String getBucketName() {
return mBucketName;
}
public void setBucketName(String bucketName) {
mBucketName = bucketName;
}
public String getMimeType() {
return mMimeType;
}
public void setMimeType(String mimeType) {
mMimeType = mimeType;
}
public long getAddDate() {
return mAddDate;
}
public void setAddDate(long addDate) {
mAddDate = addDate;
}
public float getLatitude() {
return mLatitude;
}
public void setLatitude(float latitude) {
mLatitude = latitude;
}
public float getLongitude() {
return mLongitude;
}
public void setLongitude(float longitude) {
mLongitude = longitude;
}
public long getSize() {
return mSize;
}
public void setSize(long size) {
mSize = size;
}
public long getDuration() {
return mDuration;
}
public void setDuration(long duration) {
mDuration = duration;
}
public String getThumbPath() {
return mThumbPath;
}
public void setThumbPath(String thumbPath) {
mThumbPath = thumbPath;
}
@MediaType
public int getMediaType() {
return mMediaType;
}
public void setMediaType(@MediaType int mediaType) {
mMediaType = mediaType;
}
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean checked) {
isChecked = checked;
}
public boolean isDisable() {
return isDisable;
}
public void setDisable(boolean disable) {
this.isDisable = disable;
}
protected AlbumFile(Parcel in) {
mPath = in.readString();
mBucketName = in.readString();
mMimeType = in.readString();
mAddDate = in.readLong();
mLatitude = in.readFloat();
mLongitude = in.readFloat();
mSize = in.readLong();
mDuration = in.readLong();
mThumbPath = in.readString();
mMediaType = in.readInt();
isChecked = in.readByte() != 0;
isDisable = in.readByte() != 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mPath);
dest.writeString(mBucketName);
dest.writeString(mMimeType);
dest.writeLong(mAddDate);
dest.writeFloat(mLatitude);
dest.writeFloat(mLongitude);
dest.writeLong(mSize);
dest.writeLong(mDuration);
dest.writeString(mThumbPath);
dest.writeInt(mMediaType);
dest.writeByte((byte) (isChecked ? 1 : 0));
dest.writeByte((byte) (isDisable ? 1 : 0));
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<AlbumFile> CREATOR = new Creator<AlbumFile>() {
@Override
public AlbumFile createFromParcel(Parcel in) {
return new AlbumFile(in);
}
@Override
public AlbumFile[] newArray(int size) {
return new AlbumFile[size];
}
};
}