diff --git a/example/lib/apps_events.dart b/example/lib/apps_events.dart index 0bb059a..62e39df 100644 --- a/example/lib/apps_events.dart +++ b/example/lib/apps_events.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:device_apps/device_apps.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class AppsEventsScreen extends StatefulWidget { @@ -86,7 +85,7 @@ class _AppEventItem extends StatelessWidget { children: [ ListTile( title: Text(event.packageName), - subtitle: _AppEventItemType(event.event), + subtitle: _AppEventItemType(event), leading: Text('${event.time.hour}:${event.time.minute}'), ), const Divider() @@ -98,22 +97,17 @@ class _AppEventItem extends StatelessWidget { class _AppEventItemType extends StatelessWidget { final String _type; - _AppEventItemType(ApplicationEventType type) - : _type = _extractEventTypeName(type); - - static String _extractEventTypeName(ApplicationEventType type) { - switch (type) { - case ApplicationEventType.installed: - return 'Installed'; - case ApplicationEventType.updated: - return 'Updated'; - case ApplicationEventType.uninstalled: - return 'Uninstalled'; - case ApplicationEventType.enabled: - return 'Enabled'; - case ApplicationEventType.disabled: - return 'Disabled'; - } + _AppEventItemType(ApplicationEvent event) + : _type = _extractEventTypeName(event); + + static String _extractEventTypeName(ApplicationEvent event) { + return switch (event) { + ApplicationEventInstalled() => 'Installed', + ApplicationEventUpdated() => 'Updated', + ApplicationEventUninstalled() => 'Uninstalled', + ApplicationEventEnabled() => 'Enabled', + ApplicationEventDisabled() => 'Disabled', + }; } @override diff --git a/example/lib/apps_list.dart b/example/lib/apps_list.dart index 3a4769a..46afc88 100644 --- a/example/lib/apps_list.dart +++ b/example/lib/apps_list.dart @@ -56,8 +56,8 @@ class _AppsListScreenContent extends StatelessWidget { const _AppsListScreenContent( {Key? key, - this.includeSystemApps: false, - this.onlyAppsWithLaunchIntent: false}) + this.includeSystemApps = false, + this.onlyAppsWithLaunchIntent = false}) : super(key: key); @override @@ -80,9 +80,9 @@ class _AppsListScreenContent extends StatelessWidget { return Column( children: [ ListTile( - leading: app is ApplicationWithIcon + leading: app.icon != null ? CircleAvatar( - backgroundImage: MemoryImage(app.icon), + backgroundImage: MemoryImage(app.icon!), backgroundColor: Colors.white, ) : null, diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 4f11efe..8eb5e54 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -17,5 +17,5 @@ flutter: uses-material-design: true environment: - sdk: ">=2.12.0 <3.0.0" - flutter: ">=1.10.0" \ No newline at end of file + sdk: ">=3.0.0 <4.0.0" + flutter: ">=3.0.0" \ No newline at end of file diff --git a/lib/device_apps.dart b/lib/device_apps.dart index 5837f25..cff6273 100644 --- a/lib/device_apps.dart +++ b/lib/device_apps.dart @@ -1,3 +1,2 @@ export 'src/model/application_category.dart'; -export 'src/model/application_event.dart'; export 'src/plugin.dart'; diff --git a/lib/src/model/application_event.dart b/lib/src/model/application_event.dart deleted file mode 100644 index b40e0ec..0000000 --- a/lib/src/model/application_event.dart +++ /dev/null @@ -1,15 +0,0 @@ -enum ApplicationEventType { - // Application is installed - installed, - - // Application is updated (eg: from version 1 to 2) - updated, - // Application is uninstalled from the device - uninstalled, - - // Application is enabled by the user - enabled, - - // Application is disabled by the user (but still installed) - disabled, -} diff --git a/lib/src/plugin.dart b/lib/src/plugin.dart index b9d5357..54c3eed 100644 --- a/lib/src/plugin.dart +++ b/lib/src/plugin.dart @@ -1,12 +1,10 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:typed_data'; -import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'model/application_category.dart'; -import 'model/application_event.dart'; /// Plugin to list applications installed on an Android device /// iOS is not supported @@ -25,9 +23,9 @@ class DeviceApps { /// [onlyAppsWithLaunchIntent] will only list applications when an entrypoint. /// It is similar to what a launcher will display static Future> getInstalledApplications({ - bool includeSystemApps: false, - bool includeAppIcons: false, - bool onlyAppsWithLaunchIntent: false, + bool includeSystemApps = false, + bool includeAppIcons = false, + bool onlyAppsWithLaunchIntent = false, }) async { try { final Object apps = @@ -182,6 +180,7 @@ class _BaseApplication { /// An application installed on the device /// Depending on the Android version, some attributes may not be available +@immutable class Application extends _BaseApplication { /// Displayable name of the application final String appName; @@ -219,15 +218,16 @@ class Application extends _BaseApplication { /// or disabled (installed, but not visible) final bool enabled; + final String? _icon; + + /// Icon of the application to use in conjunction with [Image.memory] + Uint8List? get icon => _icon == null ? null : base64.decode(_icon!); + factory Application._(Map map) { if (map.length == 0) { throw Exception('The map can not be null!'); } - if (map.containsKey('app_icon')) { - return ApplicationWithIcon._fromMap(map); - } else { - return Application._fromMap(map); - } + return Application._fromMap(map); } Application._fromMap(Map map) @@ -241,6 +241,7 @@ class Application extends _BaseApplication { updateTimeMillis = map['update_time'] as int, enabled = map['is_enabled'] as bool, category = _parseCategory(map['category']), + _icon = map['app_icon'] as String?, super._fromMap(map); /// Mapping of Android categories @@ -305,6 +306,7 @@ class Application extends _BaseApplication { 'updateTimeMillis: $updateTimeMillis, ' 'category: $category, ' 'enabled: $enabled' + 'icon: $icon' '}'; } @@ -323,7 +325,8 @@ class Application extends _BaseApplication { installTimeMillis == other.installTimeMillis && updateTimeMillis == other.updateTimeMillis && category == other.category && - enabled == other.enabled; + enabled == other.enabled && + icon == other.icon; @override int get hashCode => @@ -337,36 +340,8 @@ class Application extends _BaseApplication { installTimeMillis.hashCode ^ updateTimeMillis.hashCode ^ category.hashCode ^ - enabled.hashCode; -} - -/// If the [includeAppIcons] attribute is provided, this class will be used. -/// To display an image simply use the [Image.memory] widget. -/// Example: -/// -/// ``` -/// Image.memory(app.icon) -/// ``` -class ApplicationWithIcon extends Application { - final String _icon; - - ApplicationWithIcon._fromMap(Map map) - : _icon = map['app_icon'] as String, - super._fromMap(map); - - /// Icon of the application to use in conjunction with [Image.memory] - Uint8List get icon => base64.decode(_icon); - - @override - bool operator ==(Object other) => - identical(this, other) || - super == other && - other is ApplicationWithIcon && - runtimeType == other.runtimeType && - _icon == other._icon; - - @override - int get hashCode => super.hashCode ^ _icon.hashCode; + enabled.hashCode ^ + icon.hashCode; } /// Represent an event relative to an application, which can be: @@ -378,7 +353,7 @@ class ApplicationWithIcon extends Application { /// /// Note: an [Application] is not available directly in this object, as it would /// be null in the case of an uninstallation -abstract class ApplicationEvent { +sealed class ApplicationEvent { final DateTime time; factory ApplicationEvent._(Map map) { @@ -410,12 +385,9 @@ abstract class ApplicationEvent { /// The package name of the application related to this event String get packageName; - /// The event type will help check if the app is installed or not - ApplicationEventType get event; - @override String toString() { - return 'event: $event, time: $time'; + return 'event: ${this.runtimeType}, time: $time'; } @override @@ -423,10 +395,10 @@ abstract class ApplicationEvent { identical(this, other) || other is ApplicationEvent && runtimeType == other.runtimeType && - event == other.event; + packageName == other.packageName; @override - int get hashCode => event.hashCode; + int get hashCode => runtimeType.hashCode ^ packageName.hashCode; } class ApplicationEventInstalled extends ApplicationEvent { @@ -436,9 +408,6 @@ class ApplicationEventInstalled extends ApplicationEvent { : application = Application._(map), super._fromMap(map); - @override - ApplicationEventType get event => ApplicationEventType.installed; - @override String get packageName => application.packageName; @@ -466,9 +435,6 @@ class ApplicationEventUpdated extends ApplicationEvent { : application = Application._(map), super._fromMap(map); - @override - ApplicationEventType get event => ApplicationEventType.updated; - @override String get packageName => application.packageName; @@ -499,9 +465,6 @@ class ApplicationEventUninstalled extends ApplicationEvent { @override String get packageName => _application.packageName; - @override - ApplicationEventType get event => ApplicationEventType.uninstalled; - @override bool operator ==(Object other) => identical(this, other) || @@ -526,9 +489,6 @@ class ApplicationEventEnabled extends ApplicationEvent { : application = Application._(map), super._fromMap(map); - @override - ApplicationEventType get event => ApplicationEventType.enabled; - @override String get packageName => application.packageName; @@ -556,9 +516,6 @@ class ApplicationEventDisabled extends ApplicationEvent { : application = Application._(map), super._fromMap(map); - @override - ApplicationEventType get event => ApplicationEventType.disabled; - @override String get packageName => application.packageName; diff --git a/pubspec.yaml b/pubspec.yaml index eb87dd5..d1415a9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,8 +4,8 @@ version: 2.2.0 homepage: https://github.com/g123k/flutter_plugin_device_apps environment: - sdk: '>=2.12.0 <3.0.0' - flutter: ">=1.10.0" + sdk: '>=3.0.0 <4.0.0' + flutter: ">=3.0.0" dependencies: flutter: