barinsta/app/src/main/java/awais/instagrabber/utils/MediaController.java

387 lines
18 KiB
Java

package awais.instagrabber.utils;
import android.content.Context;
import android.database.Cursor;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.util.SparseArray;
import java.util.ArrayList;
import java.util.Collections;
import awais.instagrabber.R;
/*
* This is the source code of Telegram for Android v. 1.3.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2018.
*/
public class MediaController {
private static final String TAG = MediaController.class.getSimpleName();
private static final String[] PROJECTION_PHOTOS = {
MediaStore.Images.Media._ID,
MediaStore.Images.Media.BUCKET_ID,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.DATA,
Build.VERSION.SDK_INT > 28 ? MediaStore.Images.Media.DATE_TAKEN : MediaStore.Images.Media.DATE_MODIFIED,
MediaStore.Images.Media.ORIENTATION,
MediaStore.Images.Media.WIDTH,
MediaStore.Images.Media.HEIGHT,
MediaStore.Images.Media.SIZE
};
private static final String[] PROJECTION_VIDEO = {
MediaStore.Video.Media._ID,
MediaStore.Video.Media.BUCKET_ID,
MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
MediaStore.Video.Media.DATA,
Build.VERSION.SDK_INT > 28 ? MediaStore.Video.Media.DATE_TAKEN : MediaStore.Images.Media.DATE_MODIFIED,
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media.WIDTH,
MediaStore.Video.Media.HEIGHT,
MediaStore.Video.Media.SIZE
};
private final Context context;
private final OnLoadListener onLoadListener;
private final AppExecutors appExecutors;
private static Runnable broadcastPhotosRunnable;
private ArrayList<AlbumEntry> allMediaAlbums;
private ArrayList<AlbumEntry> allPhotoAlbums;
private AlbumEntry allPhotosAlbumEntry;
private AlbumEntry allMediaAlbumEntry;
private AlbumEntry allVideosAlbumEntry;
public MediaController(final Context context, final OnLoadListener onLoadListener) {
this.context = context;
this.onLoadListener = onLoadListener;
appExecutors = AppExecutors.INSTANCE;
}
public void load() {
loadGalleryAlbums();
}
private void loadGalleryAlbums() {
final Thread thread = new Thread(() -> {
final ArrayList<AlbumEntry> mediaAlbumsSorted = new ArrayList<>();
final ArrayList<AlbumEntry> photoAlbumsSorted = new ArrayList<>();
SparseArray<AlbumEntry> mediaAlbums = new SparseArray<>();
SparseArray<AlbumEntry> photoAlbums = new SparseArray<>();
AlbumEntry allPhotosAlbum = null;
AlbumEntry allVideosAlbum = null;
AlbumEntry allMediaAlbum = null;
String cameraFolder = null;
try {
cameraFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() + "/" + "Camera/";
} catch (Exception e) {
Log.e(TAG, "loadGalleryAlbums: ", e);
}
Integer mediaCameraAlbumId = null;
Integer photoCameraAlbumId = null;
Cursor cursor = null;
try {
if (PermissionUtils.hasAttachMediaPerms(context)) {
cursor = MediaStore.Images.Media.query(context.getContentResolver(),
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
PROJECTION_PHOTOS,
null,
null,
(Build.VERSION.SDK_INT > 28
? MediaStore.Images.Media.DATE_TAKEN
: MediaStore.Images.Media.DATE_MODIFIED) + " DESC");
if (cursor != null) {
int imageIdColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID);
int bucketIdColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID);
int bucketNameColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
int dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
int dateColumn = cursor.getColumnIndex(Build.VERSION.SDK_INT > 28 ? MediaStore.Images.Media.DATE_TAKEN
: MediaStore.Images.Media.DATE_MODIFIED);
int orientationColumn = cursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION);
int widthColumn = cursor.getColumnIndex(MediaStore.Images.Media.WIDTH);
int heightColumn = cursor.getColumnIndex(MediaStore.Images.Media.HEIGHT);
int sizeColumn = cursor.getColumnIndex(MediaStore.Images.Media.SIZE);
while (cursor.moveToNext()) {
String path = cursor.getString(dataColumn);
if (TextUtils.isEmpty(path)) {
continue;
}
int imageId = cursor.getInt(imageIdColumn);
int bucketId = cursor.getInt(bucketIdColumn);
String bucketName = cursor.getString(bucketNameColumn);
long dateTaken = cursor.getLong(dateColumn);
int orientation = cursor.getInt(orientationColumn);
int width = cursor.getInt(widthColumn);
int height = cursor.getInt(heightColumn);
long size = cursor.getLong(sizeColumn);
MediaEntry mediaEntry = new MediaEntry(bucketId, imageId, dateTaken, path, orientation, -1, false, width, height, size);
if (allPhotosAlbum == null) {
allPhotosAlbum = new AlbumEntry(0, context.getString(R.string.all_photos), mediaEntry);
photoAlbumsSorted.add(0, allPhotosAlbum);
}
if (allMediaAlbum == null) {
allMediaAlbum = new AlbumEntry(0, context.getString(R.string.all_media), mediaEntry);
mediaAlbumsSorted.add(0, allMediaAlbum);
}
allPhotosAlbum.addPhoto(mediaEntry);
allMediaAlbum.addPhoto(mediaEntry);
AlbumEntry albumEntry = mediaAlbums.get(bucketId);
if (albumEntry == null) {
albumEntry = new AlbumEntry(bucketId, bucketName, mediaEntry);
mediaAlbums.put(bucketId, albumEntry);
if (mediaCameraAlbumId == null && cameraFolder != null && path.startsWith(cameraFolder)) {
mediaAlbumsSorted.add(0, albumEntry);
mediaCameraAlbumId = bucketId;
} else {
mediaAlbumsSorted.add(albumEntry);
}
}
albumEntry.addPhoto(mediaEntry);
albumEntry = photoAlbums.get(bucketId);
if (albumEntry == null) {
albumEntry = new AlbumEntry(bucketId, bucketName, mediaEntry);
photoAlbums.put(bucketId, albumEntry);
if (photoCameraAlbumId == null && cameraFolder != null && path.startsWith(cameraFolder)) {
photoAlbumsSorted.add(0, albumEntry);
photoCameraAlbumId = bucketId;
} else {
photoAlbumsSorted.add(albumEntry);
}
}
albumEntry.addPhoto(mediaEntry);
}
}
}
} catch (Throwable e) {
Log.e(TAG, "loadGalleryAlbums: ", e);
} finally {
if (cursor != null) {
try {
cursor.close();
} catch (Exception e) {
Log.e(TAG, "loadGalleryAlbums: ", e);
}
}
}
try {
if (PermissionUtils.hasAttachMediaPerms(context)) {
cursor = MediaStore.Images.Media.query(context.getContentResolver(),
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
PROJECTION_VIDEO,
MediaStore.Video.Media.MIME_TYPE + "=?",
new String[]{"video/mp4"},
(Build.VERSION.SDK_INT > 28
? MediaStore.Video.Media.DATE_TAKEN
: MediaStore.Video.Media.DATE_MODIFIED) + " DESC");
if (cursor != null) {
int imageIdColumn = cursor.getColumnIndex(MediaStore.Video.Media._ID);
int bucketIdColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_ID);
int bucketNameColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_DISPLAY_NAME);
int dataColumn = cursor.getColumnIndex(MediaStore.Video.Media.DATA);
int dateColumn = cursor.getColumnIndex(Build.VERSION.SDK_INT > 28 ? MediaStore.Video.Media.DATE_TAKEN
: MediaStore.Video.Media.DATE_MODIFIED);
int durationColumn = cursor.getColumnIndex(MediaStore.Video.Media.DURATION);
int widthColumn = cursor.getColumnIndex(MediaStore.Video.Media.WIDTH);
int heightColumn = cursor.getColumnIndex(MediaStore.Video.Media.HEIGHT);
int sizeColumn = cursor.getColumnIndex(MediaStore.Video.Media.SIZE);
while (cursor.moveToNext()) {
String path = cursor.getString(dataColumn);
if (TextUtils.isEmpty(path)) {
continue;
}
int imageId = cursor.getInt(imageIdColumn);
int bucketId = cursor.getInt(bucketIdColumn);
String bucketName = cursor.getString(bucketNameColumn);
long dateTaken = cursor.getLong(dateColumn);
long duration = cursor.getLong(durationColumn);
int width = cursor.getInt(widthColumn);
int height = cursor.getInt(heightColumn);
long size = cursor.getLong(sizeColumn);
MediaEntry mediaEntry = new MediaEntry(bucketId, imageId, dateTaken, path, -1, duration, true, width, height, size);
if (allVideosAlbum == null) {
allVideosAlbum = new AlbumEntry(0, context.getString(R.string.all_videos), mediaEntry);
allVideosAlbum.videoOnly = true;
int index = 0;
if (allMediaAlbum != null) {
index++;
}
if (allPhotosAlbum != null) {
index++;
}
mediaAlbumsSorted.add(index, allVideosAlbum);
}
if (allMediaAlbum == null) {
allMediaAlbum = new AlbumEntry(0, context.getString(R.string.all_media), mediaEntry);
mediaAlbumsSorted.add(0, allMediaAlbum);
}
allVideosAlbum.addPhoto(mediaEntry);
allMediaAlbum.addPhoto(mediaEntry);
AlbumEntry albumEntry = mediaAlbums.get(bucketId);
if (albumEntry == null) {
albumEntry = new AlbumEntry(bucketId, bucketName, mediaEntry);
mediaAlbums.put(bucketId, albumEntry);
if (mediaCameraAlbumId == null && cameraFolder != null && path.startsWith(cameraFolder)) {
mediaAlbumsSorted.add(0, albumEntry);
mediaCameraAlbumId = bucketId;
} else {
mediaAlbumsSorted.add(albumEntry);
}
}
albumEntry.addPhoto(mediaEntry);
}
}
}
} catch (Throwable e) {
Log.e(TAG, "loadGalleryAlbums: ", e);
} finally {
if (cursor != null) {
try {
cursor.close();
} catch (Exception e) {
Log.e(TAG, "loadGalleryAlbums: ", e);
}
}
}
for (int a = 0; a < mediaAlbumsSorted.size(); a++) {
Collections.sort(mediaAlbumsSorted.get(a).photos, (o1, o2) -> {
if (o1.dateTaken < o2.dateTaken) {
return 1;
} else if (o1.dateTaken > o2.dateTaken) {
return -1;
}
return 0;
});
}
broadcastNewPhotos(mediaAlbumsSorted, photoAlbumsSorted, mediaCameraAlbumId, allMediaAlbum, allPhotosAlbum, allVideosAlbum, 0);
});
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
private void broadcastNewPhotos(final ArrayList<AlbumEntry> mediaAlbumsSorted,
final ArrayList<AlbumEntry> photoAlbumsSorted,
final Integer cameraAlbumIdFinal,
final AlbumEntry allMediaAlbumFinal,
final AlbumEntry allPhotosAlbumFinal,
final AlbumEntry allVideosAlbumFinal,
int delay) {
if (broadcastPhotosRunnable != null) {
appExecutors.getMainThread().cancel(broadcastPhotosRunnable);
}
appExecutors.getMainThread().execute(broadcastPhotosRunnable = () -> {
allMediaAlbums = mediaAlbumsSorted;
allPhotoAlbums = photoAlbumsSorted;
broadcastPhotosRunnable = null;
allPhotosAlbumEntry = allPhotosAlbumFinal;
allMediaAlbumEntry = allMediaAlbumFinal;
allVideosAlbumEntry = allVideosAlbumFinal;
if (onLoadListener != null) {
onLoadListener.onLoad();
}
}, delay);
}
public AlbumEntry getAllMediaAlbumEntry() {
return allMediaAlbumEntry;
}
public AlbumEntry getAllPhotosAlbumEntry() {
return allPhotosAlbumEntry;
}
public AlbumEntry getAllVideosAlbumEntry() {
return allVideosAlbumEntry;
}
public ArrayList<AlbumEntry> getAllMediaAlbums() {
return allMediaAlbums;
}
public ArrayList<AlbumEntry> getAllPhotoAlbums() {
return allPhotoAlbums;
}
public static class AlbumEntry {
public int bucketId;
public boolean videoOnly;
public String bucketName;
public MediaEntry coverPhoto;
public ArrayList<MediaEntry> photos = new ArrayList<>();
public SparseArray<MediaEntry> photosByIds = new SparseArray<>();
public AlbumEntry(int bucketId, String bucketName, MediaEntry coverPhoto) {
this.bucketId = bucketId;
this.bucketName = bucketName;
this.coverPhoto = coverPhoto;
}
public void addPhoto(MediaEntry mediaEntry) {
photos.add(mediaEntry);
photosByIds.put(mediaEntry.imageId, mediaEntry);
}
}
public static class MediaEntry {
public int bucketId;
public int imageId;
public long dateTaken;
public long duration;
public int width;
public int height;
public long size;
public String path;
public int orientation;
public boolean isVideo;
public boolean isMuted;
public boolean canDeleteAfter;
public MediaEntry(int bucketId,
int imageId,
long dateTaken,
String path,
int orientation,
long duration,
boolean isVideo,
int width,
int height,
long size) {
this.bucketId = bucketId;
this.imageId = imageId;
this.dateTaken = dateTaken;
this.path = path;
this.width = width;
this.height = height;
this.size = size;
if (isVideo) {
this.duration = duration;
} else {
this.orientation = orientation;
}
this.isVideo = isVideo;
}
}
public interface OnLoadListener {
void onLoad();
}
}