2012-06-10 21 views
8

Estoy tratando de reproducir un sonido desde la carpeta de activos cuando un usuario hace clic en una etiqueta en el WebView de mi aplicación. Descubrí que puedo usar una nueva clase que extienda WebViewClient para detectar la extensión de un enlace y, si es un archivo mp3, puede reproducirlo a través del reproductor de audio predeterminado. Pero quiero que juegue dentro de la actividad sin comenzar una nueva actividad.Android: Reproducción de un sonido activo con WebView

que utilizan los siguientes enlaces como referencias: Sound in Webview y Error creating MediaPlayer with Uri or file in assets

Pero no funcionó.

He intentado utilizar los siguientes códigos para hacerlo:

package com.rangga.test.webview.sound; 

import android.content.Intent; 
import android.content.res.AssetFileDescriptor; 
import android.media.MediaPlayer; 
import android.net.Uri; 
import android.webkit.WebView; 
import android.webkit.WebViewClient; 

public class MyWebViewClient extends WebViewClient{ 

    public MediaPlayer mp; 

    @Override 
    public boolean shouldOverrideUrlLoading(WebView view, String url){ 
     if(url.endsWith(".mp3")){ 
      mp = new MediaPlayer(); 
      AssetFileDescriptor afd = getAssets().openFd(url); 
      mp.setDataSource(afd.getFileDescriptor()); 
      mp.start(); 

      return true; 
     }else{ 
      return true; 
     } 


    } 

} 

Me aparece un error método definido en las getAssets(), he intentado googleing y dice algo acerca de pasar de un contexto. Soy muy nuevo en Android y en la programación orientada a objetos, por lo que me pregunto si esta es la forma correcta de hacerlo y si hay una explicación simple sobre qué es un contexto. Gracias.

continuación son mis códigos completos:

MainActivity.class

package com.rangga.test.webview.sound; 

import android.app.Activity; 
import android.os.Bundle; 
import android.webkit.WebView; 

public class MainActivity extends Activity { 

    WebView webMain; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     webMain = (WebView) findViewById(R.id.webMain); 

     webMain.loadUrl("file:///android_asset/webpages/test.html"); 
     webMain.setWebViewClient(new MyWebViewClient()); 
    } 


} 

EDITAR

Así los códigos funciona gracias a https://stackoverflow.com/users/488241/squonk pero ahora se produce otro problema, he actualizado el MyWebViewClient en el siguiente:

package com.rangga.test.webview.sound; 

import java.io.IOException; 

import android.content.Context; 
import android.content.res.AssetFileDescriptor; 
import android.media.MediaPlayer; 
import android.webkit.WebView; 
import android.webkit.WebViewClient; 

public class MyWebViewClient extends WebViewClient{ 

    public MediaPlayer mp; 
    private Context context = null; 

    public MyWebViewClient(Context c){ 
     this.context = c; 
    } 

    @Override 
    public boolean shouldOverrideUrlLoading(WebView view, String url){ 
     if(url.endsWith(".mp3")){ 

      mp = new MediaPlayer(); 
      try { 
       AssetFileDescriptor afd = context.getAssets().openFd(url); 
       mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); 
       afd.close(); 
       mp.prepare(); 
       mp.start(); 
      } catch (IllegalArgumentException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (IllegalStateException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 


      return true; 
     }else{ 
      return true; 
     } 
    } 
} 

Pero obtengo una java.io.FileNotFoundException, aunque la ruta parece correcta. He puesto 2 archivos mp3 en activos/páginas web/sonidos/1.mp3 y activos/páginas web/1.mp3 y utilizado los siguientes códigos html para probarlo:

<html> 
    <head> 
     <title>Test Audio</title> 
    </head> 
    <body> 
     <a href="file:///android_asset/webpages/sounds/1.mp3">File Asset</a><br/> 
     <a href="1.mp3">Same Folder</a> 
    </body> 
</html> 

Pero me sale el siguiente error en LogCat :

06-11 06:20:37.955: W/System.err(377): java.io.FileNotFoundException: file:///android_asset/webpages/1.mp3 
06-11 06:20:37.966: W/System.err(377): at android.content.res.AssetManager.openAssetFd(Native Method) 
06-11 06:20:37.974: W/System.err(377): at android.content.res.AssetManager.openFd(AssetManager.java:314) 
06-11 06:20:37.974: W/System.err(377): at com.rangga.test.webview.sound.MyWebViewClient.shouldOverrideUrlLoading(MyWebViewClient.java:30) 
06-11 06:20:37.985: W/System.err(377): at android.webkit.CallbackProxy.uiOverrideUrlLoading(CallbackProxy.java:193) 
06-11 06:20:38.000: W/System.err(377): at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:304) 
06-11 06:20:38.005: W/System.err(377): at android.os.Handler.dispatchMessage(Handler.java:99) 
06-11 06:20:38.005: W/System.err(377): at android.os.Looper.loop(Looper.java:123) 
06-11 06:20:38.014: W/System.err(377): at android.app.ActivityThread.main(ActivityThread.java:4363) 
06-11 06:20:38.014: W/System.err(377): at java.lang.reflect.Method.invokeNative(Native Method) 
06-11 06:20:38.024: W/System.err(377): at java.lang.reflect.Method.invoke(Method.java:521) 
06-11 06:20:38.024: W/System.err(377): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
06-11 06:20:38.024: W/System.err(377): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
06-11 06:20:38.054: W/System.err(377): at dalvik.system.NativeStart.main(Native Method) 

¿Hay algún problema con la forma en que llamé al archivo? Gracias antes.

RESUELTO

Thx a las sugerencias de Squonk, probé los siguientes códigos para hacer que funcione y funcionó bien, gracias Squonk!

package com.rangga.test.webview.sound; 

import java.io.IOException; 

import android.content.Context; 
import android.content.res.AssetFileDescriptor; 
import android.media.MediaPlayer; 
import android.util.Log; 
import android.webkit.WebView; 
import android.webkit.WebViewClient; 

public class MyWebViewClient extends WebViewClient{ 

    public MediaPlayer mp; 
    private Context context = null; 

    public MyWebViewClient(Context c){ 
     this.context = c; 
     mp = new MediaPlayer(); 
    } 

    @Override 
    public boolean shouldOverrideUrlLoading(WebView view, String url){ 
     if(url.endsWith(".mp3")){ 
      url = url.replace("file:///android_asset/webpages/", ""); 
      Log.i("MyWebViewClient", url); 
      try { 
       AssetFileDescriptor afd = context.getAssets().openFd(url); 
       mp = new MediaPlayer(); 
       mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); 
       afd.close(); 
       mp.prepare(); 
       mp.start(); 
      } catch (IllegalArgumentException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (IllegalStateException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 


      return true; 
     }else{ 
      return true; 
     } 
    } 
} 

Y el html para probarlo:

<html> 
    <head> 
     <title>Test Audio</title> 
    </head> 
    <body> 
     <a href="webpages/1.mp3">File Asset</a><br/> 
    </body> 
</html> 

Aunque me hizo llegar un error si repetidamente clic en él, pero esa es otra pregunta: ¿Cómo D pregunta uno cerca de uno? >. <

Respuesta

3

Cuando usted declara su MediaPLayer en MyWebViewClient, añada lo siguiente ...

public class MyWebViewClient extends WebViewClient{ 

    public MediaPlayer mp; 
    private Context context = null; // Add this line 

    ... 
} 

A continuación, añada un constructor para MyWebViewClient de la siguiente manera ...

public MyWebViewClient(Context context) { 
    this.context = context; 
} 

Luego, en shouldOverrideUrlLoading(...) obtener sus activos de la siguiente manera ...

AssetFileDescriptor afd = context.getAssets().openFd(url); 

En su MainActivity establecer el WebViewClient pasando this (que es la Actividad Context) de la siguiente manera ...

webMain.setWebViewClient(new MyWebViewClient(this)); 

También debe devolver false de shouldOverrideUrlLoading(...) si t La url termina con '.mp3' - esto muestra que su WebView está manejando cosas y que la aplicación 'host' no debe iniciar una instancia del navegador web.

EDIT: Para reproducir archivos de audio desde el directorio de activos, es necesario configurar la fuente de datos de manera diferente - véase la respuesta aceptada a play-audio-file-from-the-assets-directory.

También debe llamar al mp.prepare() antes de llamar al mp.start().

+0

Guau, gracias, al menos, corre ahora, señor, eres una leyenda ... espera ... ¡dary! Pero cuando hago clic en el enlace 1 y 3 obtiene una java.oi.FileNotFoundException, parece que la ruta en el enlace es incorrecta>.

+0

@RanggaWiratno: Vea el EDIT al final de mi respuesta. – Squonk

+0

Sí, realmente probé lo siguiente también. He agregado los parámetros en el archivo afd y agregado mp.prepare() y afd.close() antes del mp.start() después de leer este http://droidapp.co.uk/?p=272 pero lo extraño es, todavía obtengo la excepción java.io.FileNotFoundException aunque la ruta es correcta. Intenté jugar con el html pero todavía no puedo hacerlo bien File Asset
y Same Folder. He puesto 2 archivos para probarlo, en activos> páginas web> 1.mp3 y activos> páginas web> sonidos> 1.mp3 –

Cuestiones relacionadas