@@ -14,6 +14,7 @@ import 'package:http/testing.dart' as http_testing;
14
14
import 'package:zulip/api/model/model.dart' ;
15
15
import 'package:zulip/api/notifications.dart' ;
16
16
import 'package:zulip/host/android_notifications.dart' ;
17
+ import 'package:zulip/model/binding.dart' ;
17
18
import 'package:zulip/model/localizations.dart' ;
18
19
import 'package:zulip/model/narrow.dart' ;
19
20
import 'package:zulip/model/store.dart' ;
@@ -127,7 +128,8 @@ void main() {
127
128
..name.equals ('Messages' )
128
129
..importance.equals (NotificationImportance .high)
129
130
..lightsEnabled.equals (true )
130
- ..soundUri.isNull ()
131
+ ..soundUri.equals (testBinding.androidNotificationHost.fakeStoredNotificationSoundUri (
132
+ NotificationChannelManager .kDefaultNotificationSound.resourceName))
131
133
..vibrationPattern.isNotNull ().deepEquals (
132
134
NotificationChannelManager .kVibrationPattern)
133
135
;
@@ -207,6 +209,160 @@ void main() {
207
209
..vibrationPattern.isNotNull ().deepEquals (
208
210
NotificationChannelManager .kVibrationPattern);
209
211
});
212
+
213
+ test ('on Android 28 (and lower) resource file is used for notification sound' , () async {
214
+ addTearDown (testBinding.reset);
215
+ final androidNotificationHost = testBinding.androidNotificationHost;
216
+
217
+ // Override android version
218
+ testBinding.deviceInfoResult =
219
+ const AndroidDeviceInfo (sdkInt: 28 , release: '10' );
220
+
221
+ // Ensure that on Android 10, notification sounds aren't being copied to
222
+ // the media store, and resource file is used directly.
223
+ await NotificationChannelManager .ensureChannel ();
224
+ check (androidNotificationHost.takeCopySoundResourceToMediaStoreCalls ()).length.equals (0 );
225
+
226
+ final defaultSoundResourceName =
227
+ NotificationChannelManager .kDefaultNotificationSound.resourceName;
228
+ // Android resource uri.
229
+ final soundUri =
230
+ 'android.resource://com.zulip.flutter/raw/$defaultSoundResourceName ' ;
231
+ check (androidNotificationHost.takeCreatedChannels ()).single
232
+ ..id.equals (NotificationChannelManager .kChannelId)
233
+ ..name.equals ('Messages' )
234
+ ..importance.equals (NotificationImportance .high)
235
+ ..lightsEnabled.equals (true )
236
+ ..soundUri.equals (soundUri)
237
+ ..vibrationPattern.isNotNull ().deepEquals (
238
+ NotificationChannelManager .kVibrationPattern);
239
+ });
240
+
241
+ test ('notification sound resource files are being copied to the media store' , () async {
242
+ addTearDown (testBinding.reset);
243
+ final androidNotificationHost = testBinding.androidNotificationHost;
244
+
245
+ await NotificationChannelManager .ensureChannel ();
246
+ check (androidNotificationHost.takeCopySoundResourceToMediaStoreCalls ())
247
+ .deepEquals (NotificationSound .values.map ((e) => (
248
+ sourceResourceName: e.resourceName,
249
+ targetFileDisplayName: e.fileDisplayName),
250
+ ));
251
+
252
+ // Ensure the default source uri points to a file in the media store,
253
+ // rather than a resource file.
254
+ final defaultSoundResourceName =
255
+ NotificationChannelManager .kDefaultNotificationSound.resourceName;
256
+ final soundUri =
257
+ androidNotificationHost.fakeStoredNotificationSoundUri (defaultSoundResourceName);
258
+ check (androidNotificationHost.takeCreatedChannels ()).single
259
+ ..id.equals (NotificationChannelManager .kChannelId)
260
+ ..name.equals ('Messages' )
261
+ ..importance.equals (NotificationImportance .high)
262
+ ..lightsEnabled.equals (true )
263
+ ..soundUri.equals (soundUri)
264
+ ..vibrationPattern.isNotNull ().deepEquals (
265
+ NotificationChannelManager .kVibrationPattern);
266
+ });
267
+
268
+ test ('notification sounds are not copied again if they were previously copied' , () async {
269
+ addTearDown (testBinding.reset);
270
+ final androidNotificationHost = testBinding.androidNotificationHost;
271
+
272
+ // Emulate that all notifications sounds are already in the media store.
273
+ androidNotificationHost.setupStoredNotificationSounds (
274
+ NotificationSound .values.map ((e) => StoredNotificationsSound (
275
+ fileName: e.fileDisplayName,
276
+ isOwner: true ,
277
+ uri: androidNotificationHost.fakeStoredNotificationSoundUri (e.resourceName)),
278
+ ).toList (),
279
+ );
280
+
281
+ await NotificationChannelManager .ensureChannel ();
282
+ check (androidNotificationHost.takeCopySoundResourceToMediaStoreCalls ()).length.equals (0 );
283
+
284
+ final defaultSoundResourceName =
285
+ NotificationChannelManager .kDefaultNotificationSound.resourceName;
286
+ final soundUri =
287
+ androidNotificationHost.fakeStoredNotificationSoundUri (defaultSoundResourceName);
288
+ check (androidNotificationHost.takeCreatedChannels ()).single
289
+ ..id.equals (NotificationChannelManager .kChannelId)
290
+ ..name.equals ('Messages' )
291
+ ..importance.equals (NotificationImportance .high)
292
+ ..lightsEnabled.equals (true )
293
+ ..soundUri.equals (soundUri)
294
+ ..vibrationPattern.isNotNull ().deepEquals (
295
+ NotificationChannelManager .kVibrationPattern);
296
+ });
297
+
298
+ test ('new notifications sounds are copied to media store' , () async {
299
+ addTearDown (testBinding.reset);
300
+ final androidNotificationHost = testBinding.androidNotificationHost;
301
+
302
+ // Emulate that except one sound, all other sounds are already in
303
+ // media store.
304
+ androidNotificationHost.setupStoredNotificationSounds (
305
+ NotificationSound .values.map ((e) => StoredNotificationsSound (
306
+ fileName: e.fileDisplayName,
307
+ isOwner: true ,
308
+ uri: androidNotificationHost.fakeStoredNotificationSoundUri (e.resourceName)),
309
+ ).skip (1 ).toList ()
310
+ );
311
+
312
+ await NotificationChannelManager .ensureChannel ();
313
+ final firstSound = NotificationSound .values.first;
314
+ check (androidNotificationHost.takeCopySoundResourceToMediaStoreCalls ())
315
+ .single
316
+ ..sourceResourceName.equals (firstSound.resourceName)
317
+ ..targetFileDisplayName.equals (firstSound.fileDisplayName);
318
+
319
+ final defaultSoundResourceName =
320
+ NotificationChannelManager .kDefaultNotificationSound.resourceName;
321
+ final soundUri =
322
+ androidNotificationHost.fakeStoredNotificationSoundUri (defaultSoundResourceName);
323
+ check (androidNotificationHost.takeCreatedChannels ()).single
324
+ ..id.equals (NotificationChannelManager .kChannelId)
325
+ ..name.equals ('Messages' )
326
+ ..importance.equals (NotificationImportance .high)
327
+ ..lightsEnabled.equals (true )
328
+ ..soundUri.equals (soundUri)
329
+ ..vibrationPattern.isNotNull ().deepEquals (
330
+ NotificationChannelManager .kVibrationPattern);
331
+ });
332
+
333
+ test ('no recopying of existing notification sounds in the media store; default sound uri points to resource file' , () async {
334
+ addTearDown (testBinding.reset);
335
+ final androidNotificationHost = testBinding.androidNotificationHost;
336
+
337
+ androidNotificationHost.setupStoredNotificationSounds (
338
+ NotificationSound .values.map ((e) => StoredNotificationsSound (
339
+ fileName: e.fileDisplayName,
340
+ isOwner: false ,
341
+ uri: androidNotificationHost.fakeStoredNotificationSoundUri (e.resourceName)),
342
+ ).toList ()
343
+ );
344
+
345
+ // Ensure that if a notification sound with the same name already exists
346
+ // in the media store, but it wasn't copied by us, no recopying should
347
+ // happen. Additionally, the default sound uri should point to the
348
+ // resource file, not the version in the media store.
349
+ await NotificationChannelManager .ensureChannel ();
350
+ check (androidNotificationHost.takeCopySoundResourceToMediaStoreCalls ()).length.equals (0 );
351
+
352
+ final defaultSoundResourceName =
353
+ NotificationChannelManager .kDefaultNotificationSound.resourceName;
354
+ // Android resource uri.
355
+ final soundUri =
356
+ 'android.resource://com.zulip.flutter/raw/$defaultSoundResourceName ' ;
357
+ check (androidNotificationHost.takeCreatedChannels ()).single
358
+ ..id.equals (NotificationChannelManager .kChannelId)
359
+ ..name.equals ('Messages' )
360
+ ..importance.equals (NotificationImportance .high)
361
+ ..lightsEnabled.equals (true )
362
+ ..soundUri.equals (soundUri)
363
+ ..vibrationPattern.isNotNull ().deepEquals (
364
+ NotificationChannelManager .kVibrationPattern);
365
+ });
210
366
});
211
367
212
368
group ('NotificationDisplayManager show' , () {
@@ -946,6 +1102,11 @@ void main() {
946
1102
});
947
1103
}
948
1104
1105
+ extension on Subject <CopySoundResourceToMediaStoreCall > {
1106
+ Subject <String > get targetFileDisplayName => has ((x) => x.targetFileDisplayName, 'targetFileDisplayName' );
1107
+ Subject <String > get sourceResourceName => has ((x) => x.sourceResourceName, 'sourceResourceName' );
1108
+ }
1109
+
949
1110
extension NotificationChannelChecks on Subject <NotificationChannel > {
950
1111
Subject <String > get id => has ((x) => x.id, 'id' );
951
1112
Subject <int > get importance => has ((x) => x.importance, 'importance' );
0 commit comments