Skip to content

Commit

Permalink
feat(ios): Improved AudioContextConfig assertions, fix example (#1619)
Browse files Browse the repository at this point in the history
# Description

- Improve assertion error messages for `AudioContextConfig` for values
set on iOS
- Fix example, as it could and should not alternate the `options` array
for AudioContextIOS
- Improve example to show assertion errors as toast to the user
  • Loading branch information
Gustl22 authored Aug 29, 2023
1 parent 737aa94 commit df342c5
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 28 deletions.
48 changes: 30 additions & 18 deletions packages/audioplayers/example/lib/tabs/audio_context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:audioplayers_example/components/cbx.dart';
import 'package:audioplayers_example/components/drop_down.dart';
import 'package:audioplayers_example/components/tab_content.dart';
import 'package:audioplayers_example/components/tabs.dart';
import 'package:audioplayers_example/utils.dart';
import 'package:flutter/material.dart';

class AudioContextTab extends StatefulWidget {
Expand Down Expand Up @@ -82,10 +83,15 @@ class AudioContextTabState extends State<AudioContextTab>
}

void updateConfig(AudioContextConfig newConfig) {
setState(() {
audioContextConfig = newConfig;
audioContext = audioContextConfig.build();
});
try {
final context = newConfig.build();
setState(() {
audioContextConfig = newConfig;
audioContext = context;
});
} on AssertionError catch (e) {
toast(e.message.toString());
}
}

void updateAudioContextAndroid(AudioContextAndroid contextAndroid) {
Expand All @@ -94,10 +100,15 @@ class AudioContextTabState extends State<AudioContextTab>
});
}

void updateAudioContextIOS(AudioContextIOS contextIOS) {
setState(() {
audioContext = audioContext.copy(iOS: contextIOS);
});
void updateAudioContextIOS(AudioContextIOS Function() buildContextIOS) {
try {
final context = buildContextIOS();
setState(() {
audioContext = audioContext.copy(iOS: context);
});
} on AssertionError catch (e) {
toast(e.message.toString());
}
}

Widget _genericTab() {
Expand Down Expand Up @@ -194,19 +205,20 @@ class AudioContextTabState extends State<AudioContextTab>
Widget _iosTab() {
final iosOptions = AVAudioSessionOptions.values.map(
(option) {
final options = audioContext.iOS.options;
final options = {...audioContext.iOS.options};
return Cbx(
option.name,
value: options.contains(option),
({value}) {
if (value ?? false) {
options.add(option);
} else {
options.remove(option);
}
updateAudioContextIOS(
audioContext.iOS.copy(options: options),
);
updateAudioContextIOS(() {
final iosContext = audioContext.iOS.copy(options: options);
if (value ?? false) {
options.add(option);
} else {
options.remove(option);
}
return iosContext;
});
},
);
},
Expand All @@ -219,7 +231,7 @@ class AudioContextTabState extends State<AudioContextTab>
options: {for (final e in AVAudioSessionCategory.values) e: e.name},
selected: audioContext.iOS.category,
onChange: (v) => updateAudioContextIOS(
audioContext.iOS.copy(category: v),
() => audioContext.iOS.copy(category: v),
),
),
...iosOptions,
Expand Down
2 changes: 1 addition & 1 deletion packages/audioplayers/example/lib/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ extension StateExt<T extends StatefulWidget> on State<T> {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message, key: textKey),
duration: const Duration(milliseconds: 250),
duration: Duration(milliseconds: message.length * 25),
),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,11 @@ class AudioContextConfig {
);
}

AudioContextIOS buildIOS() {
if (defaultTargetPlatform == TargetPlatform.iOS) {
validateIOS();
AudioContextIOS? buildIOS() {
if (defaultTargetPlatform != TargetPlatform.iOS) {
return null;
}
validateIOS();
return AudioContextIOS(
category: respectSilence
? AVAudioSessionCategory.ambient
Expand All @@ -128,12 +129,28 @@ class AudioContextConfig {
}

void validateIOS() {
// Please create a custom [AudioContextIOS] if the generic flags cannot
// represent your needs.
if (respectSilence && route == AudioContextConfigRoute.speaker) {
throw 'On iOS it is impossible to set both `respectSilence` and route '
'`speaker`';
}
const invalidMsg =
'Invalid AudioContextConfig: On iOS it is not possible to set';
const tip = 'Please create a custom [AudioContextIOS] if the generic flags '
'cannot represent your needs.';
assert(
!(duckAudio && respectSilence),
'$invalidMsg `respectSilence` and `duckAudio`. $tip',
);
assert(
!(respectSilence && route == AudioContextConfigRoute.speaker),
'$invalidMsg `respectSilence` and route `speaker`. $tip',
);
}

@override
String toString() {
return 'AudioContextConfig('
'route: $route, '
'duckAudio: $duckAudio, '
'respectSilence: $respectSilence, '
'stayAwake: $stayAwake'
')';
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//ignore_for_file: avoid_redundant_argument_values

import 'package:audioplayers_platform_interface/audioplayers_platform_interface.dart';
import 'package:audioplayers_platform_interface/src/api/audio_context_config.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
Expand All @@ -27,6 +29,74 @@ void main() {
);
});

test('Check AudioContextConfig assertions', () async {
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
const boolValues = {true, false};
const routeValues = AudioContextConfigRoute.values;

final throwsAssertion = [];
for (final isDuckAudio in boolValues) {
for (final isRespectSilence in boolValues) {
for (final isStayAwake in boolValues) {
for (final route in routeValues) {
final config = AudioContextConfig(
duckAudio: isDuckAudio,
respectSilence: isRespectSilence,
stayAwake: isStayAwake,
route: route,
);
try {
config.build();
throwsAssertion.add(false);
} on AssertionError catch (e) {
if (e.message
.toString()
.startsWith('Invalid AudioContextConfig')) {
throwsAssertion.add(true);
} else {
fail(
'Assertion of $config does not match the expected '
'description. See: $e',
);
}
}
}
}
}
}

// Ensure assertions keep thrown on the correct cases.
expect(
throwsAssertion,
const [
true,
true,
true,
true,
true,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
true,
false,
false,
false,
false,
false,
false,
],
);
});

test('Create invalid AudioContextIOS', () async {
try {
// Throws AssertionError:
Expand Down

0 comments on commit df342c5

Please sign in to comment.