| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- import 'package:flutter/services.dart';
- import '../models/app_entry.dart';
- import '../models/system_status.dart';
- class LauncherPlatformException implements Exception {
- LauncherPlatformException(this.message);
- final String message;
- @override
- String toString() => message;
- }
- /// Thin, testable boundary around Android's package manager, volume and
- /// connectivity APIs.
- abstract class LauncherPlatform {
- Future<List<AppEntry>> listApps();
- Future<void> launchApp({
- required String packageName,
- required String activityName,
- });
- Future<bool> isDefaultHome();
- Future<bool> requestDefaultHome();
- Future<SystemStatus> getStatus();
- Future<VolumeInfo> getVolume();
- Future<void> setVolume(int index);
- }
- class NativeBridge implements LauncherPlatform {
- static const _appsChannel = MethodChannel('com.wasp.cardash_launcher/apps');
- static const _systemChannel = MethodChannel(
- 'com.wasp.cardash_launcher/system',
- );
- @override
- Future<List<AppEntry>> listApps() async {
- try {
- final raw = await _appsChannel.invokeMethod<dynamic>('listApps');
- if (raw is Map && raw['error'] != null) {
- throw LauncherPlatformException(raw['error'].toString());
- }
- if (raw is! List) return const [];
- return raw
- .whereType<Map>()
- .map(AppEntry.fromMap)
- .where(
- (app) => app.packageName.isNotEmpty && app.activityName.isNotEmpty,
- )
- .toList(growable: false);
- } on PlatformException catch (error) {
- throw LauncherPlatformException(
- error.message ?? 'Could not load installed apps.',
- );
- } on MissingPluginException {
- throw LauncherPlatformException('The Android app bridge is unavailable.');
- }
- }
- @override
- Future<void> launchApp({
- required String packageName,
- required String activityName,
- }) async {
- try {
- await _appsChannel.invokeMethod<dynamic>('launchApp', {
- 'package': packageName,
- 'activity': activityName,
- });
- } on PlatformException catch (error) {
- throw LauncherPlatformException(
- error.message ?? 'Could not open the app.',
- );
- } on MissingPluginException {
- throw LauncherPlatformException('The Android app bridge is unavailable.');
- }
- }
- @override
- Future<bool> isDefaultHome() async {
- try {
- return await _appsChannel.invokeMethod<bool>('isDefaultHome') ?? false;
- } on PlatformException {
- return false;
- } on MissingPluginException {
- return false;
- }
- }
- @override
- Future<bool> requestDefaultHome() async {
- try {
- return await _appsChannel.invokeMethod<bool>('requestDefaultHome') ??
- false;
- } on PlatformException {
- return false;
- } on MissingPluginException {
- return false;
- }
- }
- @override
- Future<SystemStatus> getStatus() async {
- try {
- final raw = await _systemChannel.invokeMethod<dynamic>('getStatus');
- return raw is Map ? SystemStatus.fromMap(raw) : const SystemStatus();
- } on PlatformException {
- return const SystemStatus();
- } on MissingPluginException {
- return const SystemStatus();
- }
- }
- @override
- Future<VolumeInfo> getVolume() async {
- try {
- final raw = await _systemChannel.invokeMethod<dynamic>('getVolume');
- return raw is Map ? VolumeInfo.fromMap(raw) : const VolumeInfo();
- } on PlatformException {
- return const VolumeInfo();
- } on MissingPluginException {
- return const VolumeInfo();
- }
- }
- @override
- Future<void> setVolume(int index) async {
- try {
- await _systemChannel.invokeMethod<dynamic>('setVolume', {'index': index});
- } on PlatformException {
- // Volume can be unavailable on some emulators; the UI keeps its local
- // value and will reconcile on the next poll.
- } on MissingPluginException {
- // Nothing to synchronise when running outside Android.
- }
- }
- }
|