-
Notifications
You must be signed in to change notification settings - Fork 75
Description
Bug Report: Android loop() doesn't start playback and play() resets looping flag
Describe the bug
On Android, the NativeAudio.loop() method sets the internal looping flag but does not actually initiate audio playback. Conversely, the NativeAudio.play() method initiates playback but explicitly resets the looping flag to false. This design makes it impossible to start a looping audio track (like BGM) with a single method call when using the Android platform.
To Reproduce
Steps to reproduce the behavior:
- Preload an audio asset using
NativeAudio.preload(). - Call
NativeAudio.loop({ assetId: 'my-bgm' }). - Observed result: Silence. The audio never starts playing.
- Alternatively, call
NativeAudio.play({ assetId: 'my-bgm' }). - Observed result: The audio plays once and stops, even if it was intended to loop.
Expected behavior
NativeAudio.loop()should initiate playback if the asset is not already playing.- Alternatively,
NativeAudio.play()should accept aloop: booleanoption, or there should be a way to ensure the looping flag persists during playback initialization.
Screenshots
N/A (Audio behavior issue)
Desktop (please complete the following information):
N/A (Plugin specific behavior on Native Android)
Smartphone (please complete the following information):
- Device: Android Device/Emulator
- OS: Android (Tested on various versions)
- Plugin Version:
@capacitor-community/native-audio^8.0.0
Additional context
Technical Analysis (Android implementation)
Analysis of the AudioDispatcher.java and AudioAsset.java source code reveals the root cause:
loop()lack ofstart():
InAudioDispatcher.java,loop()only callsmediaPlayer.setLooping(true)without callingmediaPlayer.start().
public void loop() throws Exception {
mediaPlayer.setLooping(true);
}play()forcesloop = false:
Theplay()method hardcodes the loop parameter tofalsewhen callinginvokePlay.
// AudioDispatcher.java
public void play(Double time, Callable<Void> callable) throws Exception {
invokePlay(time, false); // 'false' is hardcoded here
callable.call();
}
private void invokePlay(Double time, Boolean loop) {
...
mediaPlayer.setLooping(loop); // Forces looping to false
...
}Known Workaround
Users currently have to chain calls, which might lead to inconsistent timing:
await NativeAudio.play({ assetId: 'bgm' });
await NativeAudio.loop({ assetId: 'bgm' }); // Force looping flag while playing