Пожалуйста, простите меня, но когда я писал этот вопрос, у меня возникли некоторые идеи, поэтому вопрос может выглядеть как журнал событий, но вы можете смело переходить к части 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,
  • аудиофайл воспроизводится нормально, и время воспроизведения отражается в значении currentTime.

Согласно сайту W3Schools, canplaythrough - это последнее возможное событие, вызываемое при загрузке аудио файл.

Указанный сценарий можно воссоздать на 10% наших тестовых устройств. Эти устройства бывают разных производителей (Lenovo, Samsung) и имеют разные версии Android (5.0.1, 6.0.1). У меня также есть разные устройства этих производителей, которые работают нормально.

Я решил протестировать свое приложение с голыми костями, потому что оно быстрее, и произошло что-то странное - оно отлично работает на вышеупомянутых 10% тестовых устройств:

  • продолжительность сообщается правильно после запуска события oncanplaythrough,
  • настройка currentTime отражается в аудиоэлементе,
  • воспроизведение звука начинается с запрошенного момента.

Я был очень шокирован, поэтому проверил все возможные различия между приложениями:

  • использовались те же настройки градиента сборки
  • использовались те же версии библиотек
  • те же методы вызываются для запуска библиотеки
  • один и тот же файл AAR используется в обоих проектах

Я обнаружил одно отличие: два приложения будут хранить свои данные в разных местах. Основное приложение хранит данные в каталоге документов, мое приложение с голыми костями хранит свои данные во внешнем хранилище [так что его легче отлаживать].

После того, как я изменил путь к хранилищу для основного приложения на внешний, приложение начало нормально работать и правильно воспроизводить звук.

Я знаю, что не могу легко получить доступ к данным, которые хранятся внутри APK, но эти данные загружаются из сети и хранятся в каталоге документов, поэтому я не ожидал, что никаких ограничений не будет.

TL; DR

При загрузке аудиофайлов в аудиоэлемент HTML из каталога документов приложения в событии canplaythrough я не могу получить доступ к duration аудиоэлемента (это 0) или установить currentTime (остается на 0 до воспроизведения) . Когда тот же файл загружается из внешнего хранилища (встроенного в память), он работает нормально, и я могу получить аудиофайл duration и установить свойство currentTime.

Что я могу сделать, чтобы он работал, когда аудио находится в каталоге документов приложения?

7
Krystian 4 Авг 2017 в 14:35
Кажется, что html5-audio большую часть времени внутренне использует MediaPlayer. Это означает, что для правильной работы на плеере аудиофайлу требуются разрешения на чтение всем. Вот почему он не работает правильно на локальном хранилище, но работает на внешнем хранилище.
 – 
Jon Goodwin
6 Авг 2017 в 20:13
Но если бы у файла не было разрешения на чтение, он бы вообще не работал, в моем случае не работают только некоторые функции WebAudio: установка currentTime и продолжительность чтения. Аудио играет нормально.
 – 
Krystian
6 Авг 2017 в 22:03
Нет, некоторые элементы процесса могут иметь разрешение на чтение, а некоторые - нет. Вы просто не можете сразу прийти к такому выводу. Очевидно, это какая-то проблема с разрешением, поскольку единственное различие - расположение файла. Если нет, то время (состояние гонки) - единственное, о чем я могу думать.
 – 
Jon Goodwin
6 Авг 2017 в 23:48
Это было довольно близко, похоже, что MediaResourceGetter проекта Chromium имеет жестко запрограммированные пути, которые можно использовать. Несмотря на то, что путь /data/data существует, он ограничен подкаталогом cache.
 – 
Krystian
6 Авг 2017 в 23:55

1 ответ

Лучший ответ

Я не уверен, почему это влияет на некоторые устройства и не влияет на другие устройства, но я просмотрел исходники проекта 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;
}

Я изменил каталог документов на каталог кеша, и все работает, как ожидалось.

2
Krystian 6 Авг 2017 в 23:51