thumbnail/app icon: use display metrics in Android instead of devicePixelRatio in Flutter
This commit is contained in:
parent
bd4d792179
commit
cbacb923e7
6 changed files with 39 additions and 23 deletions
|
@ -121,12 +121,16 @@ public class AppAdapterHandler implements MethodChannel.MethodCallHandler {
|
|||
|
||||
private void getAppIcon(MethodCall call, MethodChannel.Result result) {
|
||||
String packageName = call.argument("packageName");
|
||||
Integer size = call.argument("size");
|
||||
if (packageName == null || size == null) {
|
||||
Double sizeDip = call.argument("sizeDip");
|
||||
if (packageName == null || sizeDip == null) {
|
||||
result.error("getAppIcon-args", "failed because of missing arguments", null);
|
||||
return;
|
||||
}
|
||||
|
||||
// convert DIP to physical pixels here, instead of using `devicePixelRatio` in Flutter
|
||||
float density = context.getResources().getDisplayMetrics().density;
|
||||
int size = (int) Math.round(sizeDip * density);
|
||||
|
||||
byte[] data = null;
|
||||
try {
|
||||
int iconResourceId = context.getPackageManager().getApplicationInfo(packageName, 0).icon;
|
||||
|
|
|
@ -21,6 +21,7 @@ public class ImageFileHandler implements MethodChannel.MethodCallHandler {
|
|||
public static final String CHANNEL = "deckers.thibault/aves/image";
|
||||
|
||||
private Activity activity;
|
||||
private float density;
|
||||
private MediaStoreStreamHandler mediaStoreStreamHandler;
|
||||
|
||||
public ImageFileHandler(Activity activity, MediaStoreStreamHandler mediaStoreStreamHandler) {
|
||||
|
@ -28,6 +29,13 @@ public class ImageFileHandler implements MethodChannel.MethodCallHandler {
|
|||
this.mediaStoreStreamHandler = mediaStoreStreamHandler;
|
||||
}
|
||||
|
||||
public float getDensity() {
|
||||
if (density == 0) {
|
||||
density = activity.getResources().getDisplayMetrics().density;
|
||||
}
|
||||
return density;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
|
||||
switch (call.method) {
|
||||
|
@ -63,13 +71,20 @@ public class ImageFileHandler implements MethodChannel.MethodCallHandler {
|
|||
|
||||
private void getThumbnail(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
|
||||
Map entryMap = call.argument("entry");
|
||||
Integer width = call.argument("width");
|
||||
Integer height = call.argument("height");
|
||||
Integer defaultSize = call.argument("defaultSize");
|
||||
if (entryMap == null || defaultSize == null) {
|
||||
Double widthDip = call.argument("widthDip");
|
||||
Double heightDip = call.argument("heightDip");
|
||||
Double defaultSizeDip = call.argument("defaultSizeDip");
|
||||
|
||||
if (entryMap == null || widthDip == null || heightDip == null || defaultSizeDip == null) {
|
||||
result.error("getThumbnail-args", "failed because of missing arguments", null);
|
||||
return;
|
||||
}
|
||||
// convert DIP to physical pixels here, instead of using `devicePixelRatio` in Flutter
|
||||
float density = getDensity();
|
||||
int width = (int) Math.round(widthDip * density);
|
||||
int height = (int) Math.round(heightDip * density);
|
||||
int defaultSize = (int) Math.round(defaultSizeDip * density);
|
||||
|
||||
ImageEntry entry = new ImageEntry(entryMap);
|
||||
new ImageDecodeTask(activity).execute(new ImageDecodeTask.Params(entry, width, height, defaultSize, result));
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@ class AndroidAppService {
|
|||
return {};
|
||||
}
|
||||
|
||||
static Future<Uint8List> getAppIcon(String packageName, int size) async {
|
||||
static Future<Uint8List> getAppIcon(String packageName, double size) async {
|
||||
try {
|
||||
final result = await platform.invokeMethod('getAppIcon', <String, dynamic>{
|
||||
'packageName': packageName,
|
||||
'size': size,
|
||||
'sizeDip': size,
|
||||
});
|
||||
return result as Uint8List;
|
||||
} on PlatformException catch (e) {
|
||||
|
|
|
@ -14,6 +14,7 @@ class ImageFileService {
|
|||
static const platform = MethodChannel('deckers.thibault/aves/image');
|
||||
static final StreamsChannel byteChannel = StreamsChannel('deckers.thibault/aves/imagebytestream');
|
||||
static final StreamsChannel opChannel = StreamsChannel('deckers.thibault/aves/imageopstream');
|
||||
static const double thumbnailDefaultSize = 64.0;
|
||||
|
||||
static Future<void> getImageEntries(SortFactor sort, GroupFactor group) async {
|
||||
try {
|
||||
|
@ -76,15 +77,15 @@ class ImageFileService {
|
|||
return Future.sync(() => Uint8List(0));
|
||||
}
|
||||
|
||||
static Future<Uint8List> getThumbnail(ImageEntry entry, int width, int height, {Object taskKey, int priority}) {
|
||||
static Future<Uint8List> getThumbnail(ImageEntry entry, double width, double height, {Object taskKey, int priority}) {
|
||||
return servicePolicy.call(
|
||||
() async {
|
||||
try {
|
||||
final result = await platform.invokeMethod('getThumbnail', <String, dynamic>{
|
||||
'entry': entry.toMap(),
|
||||
'width': width,
|
||||
'height': height,
|
||||
'defaultSize': 256,
|
||||
'widthDip': width,
|
||||
'heightDip': height,
|
||||
'defaultSizeDip': thumbnailDefaultSize,
|
||||
});
|
||||
return result as Uint8List;
|
||||
} on PlatformException catch (e) {
|
||||
|
|
|
@ -21,7 +21,7 @@ class AppIconImage extends ImageProvider<AppIconImageKey> {
|
|||
Future<AppIconImageKey> obtainKey(ImageConfiguration configuration) {
|
||||
return SynchronousFuture<AppIconImageKey>(AppIconImageKey(
|
||||
packageName: packageName,
|
||||
sizePixels: (size * configuration.devicePixelRatio).round(),
|
||||
size: size,
|
||||
scale: scale,
|
||||
));
|
||||
}
|
||||
|
@ -38,28 +38,28 @@ class AppIconImage extends ImageProvider<AppIconImageKey> {
|
|||
}
|
||||
|
||||
Future<ui.Codec> _loadAsync(AppIconImageKey key, DecoderCallback decode) async {
|
||||
final bytes = await AndroidAppService.getAppIcon(key.packageName, key.sizePixels);
|
||||
final bytes = await AndroidAppService.getAppIcon(key.packageName, key.size);
|
||||
return await decode(bytes ?? Uint8List(0));
|
||||
}
|
||||
}
|
||||
|
||||
class AppIconImageKey {
|
||||
final String packageName;
|
||||
final int sizePixels;
|
||||
final double size;
|
||||
final double scale;
|
||||
|
||||
const AppIconImageKey({
|
||||
@required this.packageName,
|
||||
@required this.sizePixels,
|
||||
@required this.size,
|
||||
this.scale,
|
||||
});
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
return other is AppIconImageKey && other.packageName == packageName && other.sizePixels == sizePixels && other.scale == scale;
|
||||
return other is AppIconImageKey && other.packageName == packageName && other.size == size && other.scale == scale;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(packageName, sizePixels, scale);
|
||||
int get hashCode => hashValues(packageName, size, scale);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ class ThumbnailProvider extends ImageProvider<ThumbnailProviderKey> {
|
|||
ThumbnailProviderKey _buildKey(ImageConfiguration configuration) => ThumbnailProviderKey(
|
||||
entry: entry,
|
||||
extent: extent,
|
||||
devicePixelRatio: configuration.devicePixelRatio,
|
||||
scale: scale,
|
||||
);
|
||||
|
||||
|
@ -50,8 +49,7 @@ class ThumbnailProvider extends ImageProvider<ThumbnailProviderKey> {
|
|||
}
|
||||
|
||||
Future<ui.Codec> _loadAsync(ThumbnailProviderKey key, DecoderCallback decode) async {
|
||||
final dimPixels = (extent * key.devicePixelRatio).round();
|
||||
final bytes = await ImageFileService.getThumbnail(key.entry, dimPixels, dimPixels, taskKey: _cancellationKey);
|
||||
final bytes = await ImageFileService.getThumbnail(key.entry, extent, extent, taskKey: _cancellationKey);
|
||||
return await decode(bytes ?? Uint8List(0));
|
||||
}
|
||||
|
||||
|
@ -67,13 +65,11 @@ class ThumbnailProvider extends ImageProvider<ThumbnailProviderKey> {
|
|||
class ThumbnailProviderKey {
|
||||
final ImageEntry entry;
|
||||
final double extent;
|
||||
final double devicePixelRatio; // do not include configuration in key hashcode or == operator
|
||||
final double scale;
|
||||
|
||||
const ThumbnailProviderKey({
|
||||
@required this.entry,
|
||||
@required this.extent,
|
||||
@required this.devicePixelRatio,
|
||||
this.scale,
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue