Skip to content

Commit

Permalink
fix(android): app crashes on asynchronous errors (fixes #1260)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustl22 committed Feb 11, 2023
1 parent aee480b commit b39c712
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 20 deletions.
Binary file not shown.
28 changes: 28 additions & 0 deletions packages/audioplayers/example/integration_test/lib_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:io';

import 'package:audioplayers/audioplayers.dart';
Expand Down Expand Up @@ -200,4 +201,31 @@ void main() {
skip: !features.hasForceSpeaker || !features.hasLowLatency,
);
});

group('Platform testing', () {
/// This section is to test issues for specific platforms.
/// This can be used to set up scenarios which are hard to implement or
/// reproduce on the native side.
/// Nether the less: common native unit tests are preferred.
testWidgets(
'test #1260 - mp2',
(WidgetTester tester) async {
final completer = Completer<void>();
final player = AudioPlayer();

player.onPlayerComplete.listen(
(_) => completer.complete(),
onError: completer.completeError,
);
// The play event is handled asynchronously and therefore the error is
// not thrown while preparing the source, but returned via error stream.
await player.play(AssetSource(mp2Asset));
await completer.future;
// TODO(gustl22): check error via stream, if supported via #1352
// Unexpected platform error: MediaPlayer error with
// what:MEDIA_ERROR_UNKNOWN {what:1} extra:MEDIA_ERROR_SYSTEM
},
skip: kIsWeb || !Platform.isAndroid,
);
});
}
1 change: 1 addition & 0 deletions packages/audioplayers/example/lib/tabs/sources.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const mpgaStreamUrl = 'https://timesradio.wireless.radio/stream';

const asset1 = 'laser.wav';
const asset2 = 'nasa_on_a_mission.mp3';
const mp2Asset = 'two_beeps.mp2';

class SourcesTab extends StatefulWidget {
final AudioPlayer player;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,22 +247,47 @@ class WrappedPlayer internal constructor(
* Player callbacks
*/
fun onPrepared() {
prepared = true
ref.handleDuration(this)
if (playing) {
player?.start()
ref.handleIsPlaying()
}
if (shouldSeekTo >= 0 && player?.isLiveStream() != true) {
player?.seekTo(shouldSeekTo)
try {
prepared = true
ref.handleDuration(this)
if (playing) {
player?.start()
ref.handleIsPlaying()
}
if (shouldSeekTo >= 0 && player?.isLiveStream() != true) {
player?.seekTo(shouldSeekTo)
}
} catch (e: Exception) {
handleError(e)
}
}

fun onCompletion() {
if (releaseMode != ReleaseMode.LOOP) {
stop()
try {
if (releaseMode != ReleaseMode.LOOP) {
stop()
}
ref.handleComplete(this)
} catch (e: Exception) {
handleError(e)
}
ref.handleComplete(this)
}

@Suppress("UNUSED_PARAMETER")
fun onBuffering(percent: Int) {
// TODO(luan): expose this as a stream
}

fun onSeekComplete() {
try {
ref.handleSeekComplete(this)
} catch (e: Exception) {
handleError(e)
}
}

private fun handleError(error: Throwable) {
ref.handleError(this, error.stackTraceToString())
}

fun onError(what: Int, extra: Int): Boolean {
Expand All @@ -283,15 +308,6 @@ class WrappedPlayer internal constructor(
return false
}

@Suppress("UNUSED_PARAMETER")
fun onBuffering(percent: Int) {
// TODO(luan): expose this as a stream
}

fun onSeekComplete() {
ref.handleSeekComplete(this)
}

/**
* Internal logic. Private methods
*/
Expand Down

0 comments on commit b39c712

Please sign in to comment.