From cb102cbc6ba073a6fd470ed27309213fc7fa6d47 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Mon, 16 Aug 2021 10:42:50 +0900 Subject: [PATCH] improved app icon fetch --- .../aves/channel/calls/AppAdapterHandler.kt | 39 ++++++++++--------- .../app_icon_image_provider.dart | 6 +-- lib/services/android_app_service.dart | 4 +- lib/utils/constants.dart | 5 +++ lib/widgets/viewer/info/basic_section.dart | 25 ++++++------ pubspec.lock | 2 +- pubspec.yaml | 1 + 7 files changed, 43 insertions(+), 39 deletions(-) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AppAdapterHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AppAdapterHandler.kt index ef30b56ab..3b1decf34 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AppAdapterHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AppAdapterHandler.kt @@ -3,6 +3,7 @@ package deckers.thibault.aves.channel.calls import android.content.* import android.content.pm.ApplicationInfo import android.content.res.Configuration +import android.content.res.Resources import android.net.Uri import android.os.Handler import android.os.Looper @@ -103,27 +104,29 @@ class AppAdapterHandler(private val context: Context) : MethodCallHandler { var data: ByteArray? = null try { val iconResourceId = context.packageManager.getApplicationInfo(packageName, 0).icon - val uri = Uri.Builder() - .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) - .authority(packageName) - .path(iconResourceId.toString()) - .build() + if (iconResourceId != Resources.ID_NULL) { + val uri = Uri.Builder() + .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) + .authority(packageName) + .path(iconResourceId.toString()) + .build() - val options = RequestOptions() - .format(DecodeFormat.PREFER_RGB_565) - .override(size, size) - val target = Glide.with(context) - .asBitmap() - .apply(options) - .load(uri) - .submit(size, size) + val options = RequestOptions() + .format(DecodeFormat.PREFER_RGB_565) + .override(size, size) + val target = Glide.with(context) + .asBitmap() + .apply(options) + .load(uri) + .submit(size, size) - try { - data = target.get()?.getBytes(canHaveAlpha = true, recycle = false) - } catch (e: Exception) { - Log.w(LOG_TAG, "failed to decode app icon for packageName=$packageName", e) + try { + data = target.get()?.getBytes(canHaveAlpha = true, recycle = false) + } catch (e: Exception) { + Log.w(LOG_TAG, "failed to decode app icon for packageName=$packageName", e) + } + Glide.with(context).clear(target) } - Glide.with(context).clear(target) } catch (e: Exception) { Log.w(LOG_TAG, "failed to get app info for packageName=$packageName", e) return diff --git a/lib/image_providers/app_icon_image_provider.dart b/lib/image_providers/app_icon_image_provider.dart index 91aecf1ac..3628e7481 100644 --- a/lib/image_providers/app_icon_image_provider.dart +++ b/lib/image_providers/app_icon_image_provider.dart @@ -4,6 +4,7 @@ import 'package:aves/services/android_app_service.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; +import 'package:transparent_image/transparent_image.dart'; class AppIconImage extends ImageProvider { const AppIconImage({ @@ -39,10 +40,7 @@ class AppIconImage extends ImageProvider { Future _loadAsync(AppIconImageKey key, DecoderCallback decode) async { try { final bytes = await AndroidAppService.getAppIcon(key.packageName, key.size); - if (bytes.isEmpty) { - throw StateError('$packageName app icon loading failed'); - } - return await decode(bytes); + return await decode(bytes.isEmpty ? kTransparentImage : bytes); } catch (error) { debugPrint('$runtimeType _loadAsync failed with packageName=$packageName, error=$error'); throw StateError('$packageName app icon decoding failed'); diff --git a/lib/services/android_app_service.dart b/lib/services/android_app_service.dart index 20514f4ca..09314686b 100644 --- a/lib/services/android_app_service.dart +++ b/lib/services/android_app_service.dart @@ -34,8 +34,8 @@ class AndroidAppService { 'sizeDip': size, }); if (result != null) return result as Uint8List; - } on PlatformException catch (e, stack) { - await reportService.recordError(e, stack); + } on PlatformException catch (_, __) { + // ignore, as some packages legitimately do not have icons } return Uint8List(0); } diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart index fbc713a6d..f714f3497 100644 --- a/lib/utils/constants.dart +++ b/lib/utils/constants.dart @@ -274,6 +274,11 @@ class Constants { license: 'Apache 2.0', sourceUrl: 'https://github.com/DavBfr/dart_pdf', ), + Dependency( + name: 'Transparent Image', + license: 'MIT', + sourceUrl: 'https://pub.dev/packages/transparent_image', + ), Dependency( name: 'Tuple', license: 'BSD 2-Clause', diff --git a/lib/widgets/viewer/info/basic_section.dart b/lib/widgets/viewer/info/basic_section.dart index 5f0876519..9fe1daf08 100644 --- a/lib/widgets/viewer/info/basic_section.dart +++ b/lib/widgets/viewer/info/basic_section.dart @@ -168,23 +168,20 @@ class _OwnerPropState extends State { text: context.l10n.viewerInfoLabelOwner, style: InfoRowGroup.keyStyle, ), - // `com.android.shell` is the package reported - // for images copied to the device by ADB for Test Driver - if (ownerPackage != 'com.android.shell') - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Image( - image: AppIconImage( - packageName: ownerPackage, - size: iconSize, - ), - width: iconSize, - height: iconSize, + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Image( + image: AppIconImage( + packageName: ownerPackage, + size: iconSize, ), + width: iconSize, + height: iconSize, ), ), + ), TextSpan( text: appName, style: InfoRowGroup.baseStyle, diff --git a/pubspec.lock b/pubspec.lock index b060c499d..8bdff5bdf 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -981,7 +981,7 @@ packages: source: hosted version: "0.3.19" transparent_image: - dependency: transitive + dependency: "direct main" description: name: transparent_image url: "https://pub.dartlang.org" diff --git a/pubspec.yaml b/pubspec.yaml index e8c22c1d3..3c8d2688a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,6 +59,7 @@ dependencies: streams_channel: git: url: git://github.com/deckerst/aves_streams_channel.git + transparent_image: tuple: url_launcher: version: