为什么我无法在Android WebView的HTML AudioElement中设置currentTime和duration等于0?

Kry*_*ian 7 android webview html5-audio

请原谅我,但是当我写这个问题时,出现了一些想法,所以问题可能看起来像是事件的日志,但你可以安全地跳到TL; DR部分.

我有一个AAR模块,我在其中使用a WebView来显示页面并播放具有不同开始时间的音频文件 - 具体取决于上下文.我有两个应用程序,我测试AAR模块:一个测试应用程序,这是运行模块所需的简单工具,以及真正的应用程序需要一段时间才能通过应用程序流程进入模块部分.

我被告知几个测试设备上的错误,其中音频播放始终从0开始,更不用说使用的音频元素currentTime设置了.

这是我的代码,处理回放:

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();
Run Code Online (Sandbox Code Playgroud)

正如评论中所述,我添加了几个断点来检查发生了什么,这里有一些结论:

  • oncanplaythrough调用事件后,持续时间设置为0,
  • 当将音频元素设置currentTime为某个值以外的值时0,它保持在0,
  • 音频文件播放正常,播放时间反映在currentTime值中.

根据W3Schools网站,canplaythrough是加载音频文件时调用的最后一个可能事件.

提到的场景可以在10%的测试设备上重新创建.这些设备来自不同的制造商(联想,三星),并有不同的Android版本(5.0.1,6.0.1).我也有来自这些制造商的不同设备可以正常工作.

我决定使用我的裸骨应用程序进行测试,因为它更快,并且发生了一些奇怪的事情 - 它在上面提到的10%的测试设备上工作正常:

  • oncanplaythrough事件被触发后正确报告持续时间,
  • 设置currentTime反映在音频元素中,
  • 音频从请求的时刻开始播放.

我很震惊,所以我检查了应用程序之间的所有可能的差异:

  • 使用相同的构建gradle设置
  • 使用了相同版本的库
  • 调用相同的方法来启动库
  • AAR两个项目中都使用相同的文件

我发现了一个区别,两个应用程序会将他们的数据存储在不同的地方.主应用程序,将数据存储在文档目录中,我的裸骨应用程序将其数据存储在外部存储中[因此更容易调试].

在我将主应用程序的存储路径更改为外部之后,应用程序开始正常工作并正确播放音频.

我知道我无法轻易访问存储在其中的数据,APK但这些数据是从网络下载并存储在文档目录中的,所以我希望不会有任何限制.

TL; DR

当从app的文档目录加载HTML的音频元素中的音频文件时,在该canplaythrough事件中,我无法访问音频元素duration(它为0)也没有设置currentTime(在播放之前保持为0).当从外部存储器(内置内存)加载相同的文件时,它工作正常,我可以获取音频文件duration并设置currentTime属性.

当音频位于应用程序的文档目录中时,我该怎么做才能使其正常工作?

Kry*_*ian 2

我不确定为什么它会影响某些设备,并且不会影响其他设备,但我浏览了 Chromium 项目的来源并偶然发现了这一点:

https://chromium.googlesource.com/chromium/src/+/61c6121a6cb9dc16f9786830655049d68dcde67c/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java

更准确地说:

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;
}
Run Code Online (Sandbox Code Playgroud)

我已将文档目录更改为缓存目录,一切都按预期进行。