mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-28 23:08:59 +02:00
fix(notifications): restore verification alert sound
This commit is contained in:
@@ -443,8 +443,21 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
'Verification required for $normalizedExtensionId while app is in '
|
||||
'background; deferring challenge until the app is foregrounded',
|
||||
);
|
||||
unawaited(_notificationService.showVerificationRequired());
|
||||
try {
|
||||
await _notificationService.showVerificationRequired();
|
||||
} catch (error) {
|
||||
_log.w(
|
||||
'Failed to show the verification-required notification: $error',
|
||||
);
|
||||
}
|
||||
await _waitForForeground();
|
||||
try {
|
||||
await _notificationService.cancelVerificationRequired();
|
||||
} catch (error) {
|
||||
_log.w(
|
||||
'Failed to clear the verification-required notification: $error',
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -30,9 +30,14 @@ class NotificationService {
|
||||
static const int downloadProgressId = 1;
|
||||
static const int updateDownloadId = 2;
|
||||
static const int libraryScanId = 3;
|
||||
static const int verificationRequiredId = 4;
|
||||
static const String channelId = 'download_progress';
|
||||
static const String channelName = 'Download Progress';
|
||||
static const String channelDescription = 'Shows download progress for tracks';
|
||||
static const String alertChannelId = 'download_alerts_v1';
|
||||
static const String alertChannelName = 'Download Alerts';
|
||||
static const String alertChannelDescription =
|
||||
'Important download status and actions that need attention';
|
||||
static const String libraryChannelId = 'library_scan';
|
||||
static const String libraryChannelName = 'Library Scan';
|
||||
static const String libraryChannelDescription =
|
||||
@@ -57,7 +62,7 @@ class NotificationService {
|
||||
|
||||
await _notifications.initialize(settings: initSettings);
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
if (!kIsWeb && defaultTargetPlatform == TargetPlatform.android) {
|
||||
final androidImpl = _notifications
|
||||
.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin
|
||||
@@ -73,6 +78,16 @@ class NotificationService {
|
||||
enableVibration: false,
|
||||
),
|
||||
);
|
||||
await androidImpl?.createNotificationChannel(
|
||||
const AndroidNotificationChannel(
|
||||
alertChannelId,
|
||||
alertChannelName,
|
||||
description: alertChannelDescription,
|
||||
importance: Importance.defaultImportance,
|
||||
playSound: true,
|
||||
enableVibration: true,
|
||||
),
|
||||
);
|
||||
await androidImpl?.createNotificationChannel(
|
||||
const AndroidNotificationChannel(
|
||||
libraryChannelId,
|
||||
@@ -147,14 +162,30 @@ class NotificationService {
|
||||
bool presentBadge = false,
|
||||
bool presentSound = false,
|
||||
}) {
|
||||
assert(!library || !playSound);
|
||||
final inProgress = progress != null;
|
||||
assert(!inProgress || !playSound);
|
||||
final androidChannelId = library
|
||||
? libraryChannelId
|
||||
: playSound
|
||||
? alertChannelId
|
||||
: channelId;
|
||||
final androidChannelName = library
|
||||
? libraryChannelName
|
||||
: playSound
|
||||
? alertChannelName
|
||||
: channelName;
|
||||
final androidChannelDescription = library
|
||||
? libraryChannelDescription
|
||||
: playSound
|
||||
? alertChannelDescription
|
||||
: channelDescription;
|
||||
|
||||
return NotificationDetails(
|
||||
android: AndroidNotificationDetails(
|
||||
library ? libraryChannelId : channelId,
|
||||
library ? libraryChannelName : channelName,
|
||||
channelDescription: library
|
||||
? libraryChannelDescription
|
||||
: channelDescription,
|
||||
androidChannelId,
|
||||
androidChannelName,
|
||||
channelDescription: androidChannelDescription,
|
||||
importance: inProgress ? Importance.low : Importance.defaultImportance,
|
||||
priority: inProgress ? Priority.low : Priority.defaultPriority,
|
||||
showProgress: inProgress,
|
||||
@@ -285,7 +316,7 @@ class NotificationService {
|
||||
'Open the app to complete verification and resume downloads';
|
||||
|
||||
await _showSafely(
|
||||
id: downloadProgressId,
|
||||
id: verificationRequiredId,
|
||||
title: title,
|
||||
body: body,
|
||||
details: _details(
|
||||
@@ -296,6 +327,10 @@ class NotificationService {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> cancelVerificationRequired() async {
|
||||
await _notifications.cancel(id: verificationRequiredId);
|
||||
}
|
||||
|
||||
Future<void> showQueueCanceled({required int canceledCount}) async {
|
||||
if (!_isInitialized) await initialize();
|
||||
if (canceledCount <= 0) return;
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:spotiflac_android/services/notification_service.dart';
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
AndroidFlutterLocalNotificationsPlugin.registerWith();
|
||||
|
||||
const channel = MethodChannel('dexterous.com/flutter/local_notifications');
|
||||
final methodCalls = <MethodCall>[];
|
||||
|
||||
setUp(() {
|
||||
debugDefaultTargetPlatformOverride = TargetPlatform.android;
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMethodCallHandler(channel, (call) async {
|
||||
methodCalls.add(call);
|
||||
if (call.method == 'initialize') return true;
|
||||
return null;
|
||||
});
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
debugDefaultTargetPlatformOverride = null;
|
||||
methodCalls.clear();
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMethodCallHandler(channel, null);
|
||||
});
|
||||
|
||||
test('verification uses a distinct audible Android alert channel', () async {
|
||||
final notificationService = NotificationService();
|
||||
await notificationService.showVerificationRequired();
|
||||
|
||||
final alertChannelCall = methodCalls.firstWhere(
|
||||
(call) =>
|
||||
call.method == 'createNotificationChannel' &&
|
||||
(call.arguments as Map<Object?, Object?>)['id'] ==
|
||||
NotificationService.alertChannelId,
|
||||
);
|
||||
final alertChannel = alertChannelCall.arguments as Map<Object?, Object?>;
|
||||
|
||||
expect(alertChannel['importance'], Importance.defaultImportance.value);
|
||||
expect(alertChannel['playSound'], isTrue);
|
||||
expect(alertChannel['enableVibration'], isTrue);
|
||||
|
||||
final showCall = methodCalls.lastWhere((call) => call.method == 'show');
|
||||
final showArguments = showCall.arguments as Map<Object?, Object?>;
|
||||
final androidDetails =
|
||||
showArguments['platformSpecifics'] as Map<Object?, Object?>;
|
||||
|
||||
expect(
|
||||
NotificationService.verificationRequiredId,
|
||||
isNot(NotificationService.downloadProgressId),
|
||||
);
|
||||
expect(showArguments['id'], NotificationService.verificationRequiredId);
|
||||
expect(androidDetails['channelId'], NotificationService.alertChannelId);
|
||||
expect(androidDetails['importance'], Importance.defaultImportance.value);
|
||||
expect(androidDetails['playSound'], isTrue);
|
||||
expect(androidDetails['enableVibration'], isTrue);
|
||||
|
||||
await notificationService.cancelVerificationRequired();
|
||||
expect(
|
||||
methodCalls.last,
|
||||
isMethodCall(
|
||||
'cancel',
|
||||
arguments: <String, Object?>{
|
||||
'id': NotificationService.verificationRequiredId,
|
||||
'tag': null,
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user