¿Por qué no puedo establecer currentTime y la duración es igual a 0 en HTML AudioElement en Android WebView?
Por favor, perdóname, pero mientras escribía esta pregunta, surgieron algunas ideas, por lo que la pregunta puede parecer un registro de eventos, pero puedes saltar con seguridad a la parte TL; DR .
Tengo un módulo AAR
en el que utilizo un WebView
para mostrar una página y reproducir archivos de audio con diferentes horas de inicio, dependiendo del contexto. Tengo dos aplicaciones donde probar el módulo AAR
: una aplicación de prueba, que es los huesos necesarios necesarios para ejecutar el módulo, y la aplicación real donde se necesita un tiempo para avanzar a través del flujo de la aplicación para llegar a la parte del módulo.
- Webview no desplazamiento después de agregar setOnTouchListener
- Cómo trabajar con ventanas emergentes ventana en android webview
- Personalizar elementos de diálogo desplegables en WebView
- Creando WebView desde Chromium para Android
- Android WebView no carga una URL HTTPS
Se me informó de un error en varios de los dispositivos de prueba, donde la reproducción de audio siempre comienza desde 0, sin importar el elemento de audio currentTime
utilizado.
Aquí está mi código, donde se maneja la reproducción:
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();
Como se indica en los comentarios, he añadido algunos puntos de interrupción para comprobar lo que está pasando, y he aquí algunas conclusiones:
- Después de que se llama al evento
oncanplaythrough
, la duración se establece en0
, - Cuando se fija
currentTime
del elemento de audio a algún valor distinto de0
, permanece en0
, - El archivo de audio se reproduce bien y el tiempo de reproducción se refleja en el valor
currentTime
.
De acuerdo con el sitio de W3Schools , canplaythrough
es el último evento posible llamado al cargar el archivo de audio.
El escenario mencionado es posible recrear en el 10% de nuestros dispositivos de prueba. Estos dispositivos vienen de diferentes fabricantes (Lenovo, Samsung) y tienen diferentes versiones de Android (5.0.1, 6.0.1). También tengo diferentes dispositivos de estos fabricantes que funcionan bien.
He decidido probar con mi aplicación de huesos, porque es más rápido, y algo extraño sucedió – funciona bien en el mencionado 10% de los dispositivos de prueba:
- Duración se informa correctamente después
oncanplaythrough
evento se dispara, - El ajuste de
currentTime
se refleja en el elemento de audio, - El audio comienza a reproducir desde el momento solicitado.
Me quedé bastante sorprendido, así que he comprobado todas las posibles diferencias entre las aplicaciones:
- Se usaron las mismas configuraciones gradle de construcción
- Se usaron las mismas versiones de bibliotecas
- Los mismos métodos se llaman para iniciar la biblioteca
- El mismo archivo
AAR
se utiliza en ambos proyectos
He encontrado una diferencia, las dos aplicaciones almacenar sus datos en diferentes lugares. La aplicación principal, almacena los datos en el directorio de documentos, mi aplicación desnuda almacena sus datos en el almacenamiento externo [por lo que es más fácil de depurar].
Después de haber cambiado la ruta de almacenamiento de la aplicación principal a externa, la aplicación comenzó a funcionar bien y reproducir el audio correctamente.
Sé que no puedo acceder fácilmente a los datos que se almacena dentro de la APK
pero estos datos se descargan de la red y se almacena en el directorio de documentos, por lo que esperaría que no se aplican limitaciones.
TL, DR
Al cargar archivos de audio en el elemento de audio de HTML desde el directorio de documentos de la aplicación, en el evento canplaythrough
, no puedo acceder a la duration
del elemento de audio (es 0) ni a currentTime
(permanece en 0 hasta que se reproduce). Cuando el mismo archivo se carga desde el almacenamiento externo (construido en la memoria) funciona bien y puedo obtener la duration
archivo de audio y establecer la propiedad currentTime
.
¿Qué puedo hacer para que funcione mientras el audio se encuentra en el directorio de documentos de la aplicación?
- WebView en Android ICS, problemas de iframe con android_assets
- Espacios en blanco usando la vista web de android dentro de scrollview con una red móvil de jQuery
- Cómo guardar la URL actual en Android Kivy Application
- Android WebView dentro de ScrollView solo desplaza scrollview
- Cómo ocultar unhide webview en android
- Enlaces que no funcionan dentro de un WebView debido a 'X-Frame-Options' establecido en 'SAMEORIGIN'
- Android- PhoneGap / WebView ignora las metaetiquetas de la ventana de visualización?
- Ocultar elemento HTML en Android WebView?
No estoy seguro de por qué afecta a algunos dispositivos, y no afecta a otros dispositivos, pero fui a través de las fuentes del proyecto Chromium y tropezó con esto:
Y para ser más exactos:
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; }
He cambiado el directorio de los documentos al directorio del escondrijo y todo trabaja como esperado.
- Android – NotificationCompat.Builder que apila las notificaciones con setGroup (grupo) que no funciona
- Android StrictMode Throwable: Método de terminación explícito 'end' no llamado