package im.actor.core.utils;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import java.util.ArrayList;
import java.util.HashMap;
import im.actor.core.viewmodel.GalleryVM;
import im.actor.runtime.Log;
import im.actor.runtime.actors.Actor;
import im.actor.runtime.collections.SparseArray;
public class GalleryScannerActor extends Actor {
public static final String TAG = "GALLERY_SCANNER";
public static final int CHECK_NEW_DELAY = 1000;
public static final int SCAN_DELAY = 100;
Context context;
Uri uri;
Cursor cursor;
int offset = 0;
int column_index_data, column_index_folder_name, column_index_date, column_index_id, column_index_folder_id;
ArrayList<String> listOfAllImages = new ArrayList<>();
ArrayList<String> newMedia = new ArrayList<>();
String absolutePathOfImage = null;
GalleryVM galleryVM;
private static final int SCAN_COUNT = 10;
private boolean visible = false;
private boolean scanned = false;
private String[] projection;
private boolean inited = false;
private Bitmap bitmap;
public GalleryScannerActor(Context context, GalleryVM galleryVM) {
this.context = context;
this.galleryVM = galleryVM;
}
@Override
public void preStart() {
uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
private void initScan() {
Log.d(TAG, "init scan");
projection = new String[]{MediaStore.Images.Media.DATA,
MediaStore.Images.Media._ID,
MediaStore.Images.Media.BUCKET_ID,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.DATE_TAKEN};
cursor = getQuery();
if (cursor != null && cursor.getCount() > 0) {
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
column_index_id = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
column_index_folder_id = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_ID);
column_index_date = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_TAKEN);
column_index_folder_name = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
Log.d(TAG, "init scan ok - starting scan iterations");
inited = true;
self().send(new Scan());
} else {
Log.d(TAG, "init scan - no media, let's check it in " + CHECK_NEW_DELAY);
if (visible) {
schedule(new InitScan(), CHECK_NEW_DELAY);
}
}
}
private Cursor getQuery() {
try {
return context.getContentResolver().query(uri, projection, null,
null, MediaStore.Images.Media.DATE_TAKEN + " DESC");
} catch (Exception e) {
return null;
}
}
private void scan() {
Log.d(TAG, "scan");
for (int i = 0; i <= SCAN_COUNT && cursor.moveToNext(); i++) {
absolutePathOfImage = cursor.getString(column_index_data);
listOfAllImages.add(absolutePathOfImage);
}
offset += SCAN_COUNT;
scanned = offset >= cursor.getCount();
//
// Update VM after 1st batch, every 100 photos, when scanned to end
//
if (offset == SCAN_COUNT || offset % 100 == 0 || scanned) {
Log.d(TAG, "scan - update vm, offset - " + offset);
galleryVM.getGalleryMediaPath().change(new ArrayList<String>(listOfAllImages));
}
if (visible) {
if (!scanned) {
schedule(new Scan(), SCAN_DELAY);
} else {
schedule(new CheckNew(), CHECK_NEW_DELAY);
}
}
}
private void checkNew() {
Log.d(TAG, "checkNew");
cursor = getQuery();
newMedia.clear();
boolean firstCycle = true;
while (cursor != null && cursor.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data);
if (!listOfAllImages.contains(absolutePathOfImage)) {
if (firstCycle) {
firstCycle = false;
bitmap = BitmapFactory.decodeFile(absolutePathOfImage);
if (bitmap != null) {
bitmap.recycle();
newMedia.add(absolutePathOfImage);
Log.d(TAG, "checkNew - new media");
} else {
Log.d(TAG, "checkNew - new media writing, breaking for wait");
break;
}
} else {
newMedia.add(absolutePathOfImage);
}
} else {
Log.d(TAG, "checkNew - found old media, break");
break;
}
}
if (newMedia.size() > 0) {
listOfAllImages.addAll(0, newMedia);
galleryVM.getGalleryMediaPath().change(new ArrayList<>(listOfAllImages));
Log.d(TAG, "checkNew - new media add - " + newMedia.size());
}
if (visible) {
Log.d(TAG, "checkNew - visible, schedule next check in " + CHECK_NEW_DELAY);
schedule(new CheckNew(), CHECK_NEW_DELAY);
}
}
@Override
public void onReceive(Object message) {
if (message instanceof Scan) {
scan();
} else if (message instanceof InitScan) {
initScan();
} else if (message instanceof CheckNew) {
checkNew();
} else if (message instanceof Show) {
visible = true;
if (scanned) {
self().send(new CheckNew());
} else {
if (!inited) {
self().send(new InitScan());
}
}
} else if (message instanceof Hide) {
visible = false;
}
}
private static class Scan {
}
private static class InitScan {
}
private static class CheckNew {
}
public static class Show {
}
public static class Hide {
}
}