added sort/group hint to fetch from media store

This commit is contained in:
Thibault Deckers 2020-06-09 09:38:07 +09:00
parent be664f0967
commit 4dd5e9a3b8
5 changed files with 50 additions and 13 deletions

View file

@ -32,7 +32,11 @@ public class ImageFileHandler implements MethodChannel.MethodCallHandler {
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
switch (call.method) {
case "getImageEntries":
new Thread(() -> mediaStoreStreamHandler.fetchAll(activity)).start();
new Thread(() -> {
String sortBy = call.argument("sort");
String groupBy = call.argument("group");
mediaStoreStreamHandler.fetchAll(activity, sortBy, groupBy);
}).start();
result.success(null);
break;
case "getImageEntry":

View file

@ -22,9 +22,9 @@ public class MediaStoreStreamHandler implements EventChannel.StreamHandler {
// nothing
}
void fetchAll(Activity activity) {
void fetchAll(Activity activity, String sortBy, String groupBy) {
Handler handler = new Handler(Looper.getMainLooper());
new MediaStoreImageProvider().fetchAll(activity, (entry) -> handler.post(() -> eventSink.success(entry))); // 350ms
new MediaStoreImageProvider().fetchAll(activity, sortBy, groupBy, (entry) -> handler.post(() -> eventSink.success(entry))); // 350ms
handler.post(() -> eventSink.endOfStream());
}
}

View file

@ -68,9 +68,39 @@ public class MediaStoreImageProvider extends ImageProvider {
MediaStore.Video.Media.ORIENTATION,
} : new String[0]).flatMap(Stream::of).toArray(String[]::new);
public void fetchAll(Activity activity, NewEntryHandler newEntryHandler) {
fetchFrom(activity, newEntryHandler, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION);
fetchFrom(activity, newEntryHandler, MediaStore.Video.Media.EXTERNAL_CONTENT_URI, VIDEO_PROJECTION);
public void fetchAll(Activity activity, final String sortBy, final String groupBy, NewEntryHandler newEntryHandler) {
String orderBy;
switch (sortBy) {
case "size":
orderBy = MediaStore.MediaColumns.SIZE + " DESC";
break;
case "name":
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
orderBy = MediaStore.MediaColumns.RELATIVE_PATH + ", " + MediaStore.MediaColumns.BUCKET_DISPLAY_NAME + ", " + MediaStore.MediaColumns.DISPLAY_NAME;
} else {
orderBy = MediaStore.MediaColumns.DATA;
}
break;
default:
case "date":
switch (groupBy) {
case "album":
// TODO TLAD find album order first
case "month":
case "day":
default:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
orderBy = MediaStore.MediaColumns.DATE_TAKEN + " DESC";
} else {
orderBy = MediaStore.MediaColumns.DATE_MODIFIED + " DESC";
}
break;
}
break;
}
fetchFrom(activity, newEntryHandler, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_PROJECTION, orderBy);
fetchFrom(activity, newEntryHandler, MediaStore.Video.Media.EXTERNAL_CONTENT_URI, VIDEO_PROJECTION, orderBy);
}
@Override
@ -83,10 +113,10 @@ public class MediaStoreImageProvider extends ImageProvider {
};
if (mimeType.startsWith(MimeTypes.IMAGE)) {
Uri contentUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
entryCount = fetchFrom(context, onSuccess, contentUri, IMAGE_PROJECTION);
entryCount = fetchFrom(context, onSuccess, contentUri, IMAGE_PROJECTION, null);
} else if (mimeType.startsWith(MimeTypes.VIDEO)) {
Uri contentUri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id);
entryCount = fetchFrom(context, onSuccess, contentUri, VIDEO_PROJECTION);
entryCount = fetchFrom(context, onSuccess, contentUri, VIDEO_PROJECTION, null);
}
if (entryCount == 0) {
callback.onFailure(new Exception("failed to fetch entry at uri=" + uri));
@ -94,8 +124,7 @@ public class MediaStoreImageProvider extends ImageProvider {
}
@SuppressLint("InlinedApi")
private int fetchFrom(final Context context, NewEntryHandler newEntryHandler, final Uri contentUri, String[] projection) {
String orderBy = MediaStore.MediaColumns.DATE_TAKEN + " DESC";
private int fetchFrom(final Context context, NewEntryHandler newEntryHandler, final Uri contentUri, String[] projection, String orderBy) {
int entryCount = 0;
final boolean needDuration = projection == VIDEO_PROJECTION;

View file

@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:aves/model/collection_lens.dart';
import 'package:aves/model/image_entry.dart';
import 'package:aves/services/service_policy.dart';
import 'package:flutter/foundation.dart';
@ -14,9 +15,12 @@ class ImageFileService {
static final StreamsChannel byteChannel = StreamsChannel('deckers.thibault/aves/imagebytestream');
static final StreamsChannel opChannel = StreamsChannel('deckers.thibault/aves/imageopstream');
static Future<void> getImageEntries() async {
static Future<void> getImageEntries(SortFactor sort, GroupFactor group) async {
try {
await platform.invokeMethod('getImageEntries');
await platform.invokeMethod('getImageEntries', <String, dynamic>{
'sort': sort.toString().replaceAll('SortFactor.', ''),
'group': group.toString().replaceAll('GroupFactor.', ''),
});
} on PlatformException catch (e) {
debugPrint('getImageEntries failed with code=${e.code}, exception=${e.message}, details=${e.details}');
}

View file

@ -63,6 +63,6 @@ class MediaStoreSource {
// TODO split image fetch AND/OR cache fetch across sessions
debugPrint('$runtimeType stream start at ${stopwatch.elapsed.inMilliseconds}ms');
await ImageFileService.getImageEntries(); // 460ms
await ImageFileService.getImageEntries(settings.collectionSortFactor, settings.collectionGroupFactor); // 460ms
}
}