android - 为什么我不能在 Android WebView 的 HTML AudioElement 中设置 currentTime 和 duration 等于 0?

标签 android webview html5-audio

请原谅我,但在我写这个问题时,出现了一些想法,所以这个问题可能看起来像是事件日志,但您可以放心地跳到 TL;DR 部分。

我有一个 AAR 模块,我在其中使用 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();

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

  • oncanplaythrough事件调用后,时长​​设置为0
  • 将音频元素的 currentTime 设置为 0 以外的某个值时,它保持在 0
  • 音频文件播放正常,播放时间反射(reflect)在 currentTime 值中。

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

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

我决定使用我的基本应用程序进行测试,因为它更快,并且发生了一些奇怪的事情 - 它在上述 10% 的测试设备上运行良好:

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

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

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

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

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

我知道我无法轻松访问存储在 APK 中的数据,但这些数据是从网络下载并存储在文档目录中的,因此我希望没有任何限制。

长话短说

当从应用程序的文档目录加载 HTML 音频元素中的音频文件时,在 canplaythrough 事件中,我无法访问音频元素的 duration(为 0)也无法设置 currentTime(在播放之前保持为 0)。当从外部存储(内置内存)加载同一文件时,它工作正常,我可以获得音频文件 duration 并设置 currentTime 属性。

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

最佳答案

我不确定为什么它会影响某些设备,而不会影响其他设备,但我浏览了 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;
}

我已将文档目录更改为缓存目录,一切正常。

关于android - 为什么我不能在 Android WebView 的 HTML AudioElement 中设置 currentTime 和 duration 等于 0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45505808/

相关文章:

android - 保存共享首选项需要很多时间

Android:如何均匀分配重量

java - 如何通过android应用程序发送短信?

java - WebView 不重新加载具有相同 URL 的页面

javascript - ajax 函数成功事件时关闭 webview

java - 在 Android 应用程序中打开链接而不是打开 Web View

android图像上传,文件在服务器中损坏

html5 音频 mp3 在 firefox 中不工作

javascript - 使用 HTML5 音频和 jQuery 调用对象 (this) 的引用

javascript - 扩展 Audio/HTMLMediaElement javascript 对象