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