Please forgive me, but as I was writing this question, some ideas came up, so the question may look as a log of events, but you can safely skip to the TL;DR part.
I have an AAR
module in which I use a WebView
to display a page and play audio files with different start time - depending on the context.
I have two apps where I test the AAR
module: a test app, which is bare bones required to run the module, and the real app where it takes a while to progress through the flow of the app to get to the module part.
I was informed about an error on several of test devices, where audio playback always starts from 0, never mind the audio element currentTime
setting used.
Here's my code, where playback is handled:
var instance = this;
this.playbackCurrentAudioPath = newBufferPath;
this.playbackCurrentAudio = document.createElement('audio');
this.playbackCurrentAudio.src = this.playbackCurrentAudioPath;
this.playbackCurrentAudio.oncanplaythrough = function () {
console.log("file loaded, try to play " + instance.playbackCurrentAudio);
instance.loaded = true;
// checked here, instance.playbackCurrentAudio.duration is equal 0
instance.playbackCurrentAudio.currentTime = audioTrackBeginTime;
// instance.playbackCurrentAudio.currentTime is equal 0
instance.playbackCurrentAudio.play();
// playback starts from the beginning of the file
};
this.playbackCurrentAudio.onerror = function () {
instance.playbackLoadError()
};
this.playbackCurrentAudio.onended = function () {
instance.playbackAudioEnded(true)
};
this.playbackCurrentAudio.load();
As stated in the comments, I have added few breakpoints to check what's going on, and here are some conclusions:
oncanplaythrough
event is called, the duration is set to 0
,currentTime
to some value other than 0
, it remains at 0
,currentTime
value.According to W3Schools site, canplaythrough
is the last possible event called when loading the audio file.
The scenario mentioned is possible to recreate on 10% of our test devices. These devices come from different manufacturers (Lenovo, Samsung) and have different Android versions (5.0.1, 6.0.1). I also have different devices from these manufacturers which work ok.
I have decided to test using my bare bones app, because it's faster, and something strange happened - it works fine on the above mentioned 10% of the test devices:
oncanplaythrough
event is fired,currentTime
is reflected in audio element,I was quite shocked, so I have checked all of the possible differences between apps:
AAR
file is used in both projectsI have found one difference, the two apps would store their data in different places. The main app, stores data in documents directory, my bare bones app stores its data in external storage [so it is easier to debug].
After I have changed the storage path for the main app to external, the app started to work fine and play the audio correctly.
I know that I cannot access easily data which is stored inside the APK
but this data is downloaded from the network and stored inside documents directory, so I would expect no limitations apply.
TL;DR
When loading audio files in HTML's audio element from app's documents directory, in the canplaythrough
event, I cannot access audio element's duration
(it's 0) nor set currentTime
(stays at 0 until played). When the same file is loaded from external storage (built in memory) it works fine and I can get the audio file duration
and set the currentTime
property.
What can I do to make it work while audio is located in app's documents directory?
I am not sure why it affects some devices, and it does not affect other devices, but I went through the sources of Chromium project and stumbled upon this:
https://chromium.googlesource.com/chromium/src/+/61c6121a6cb9dc16f9786830655049d68dcde67c/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java
and to be more exact:
private List<String> getRawAcceptableDirectories() {
List<String> result = new ArrayList<String>();
result.add("/mnt/sdcard/");
result.add("/sdcard/");
if (PACKAGE_NAME != null)
result.add("/data/data/" + PACKAGE_NAME + "/cache/");
return result;
}
I have changed the documents directory into cache directory and everything works as expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With