2012-06-10 15 views
8

Próbuję odtworzyć dźwięk z folderu zasobów, gdy użytkownik kliknie znacznik w aplikacji WebView mojej aplikacji. Odkryłem, że mogę użyć nowej klasy rozszerzającej WebViewClient, aby wykryć rozszerzenie łącza, a jeśli jest to plik mp3, może go odtworzyć za pomocą domyślnego odtwarzacza audio. Ale chcę, żeby grała w ramach działania bez rozpoczynania nowej działalności.Android: Odtwarzanie dźwięku zasobu za pomocą WebView

użyłem następujących linków jako odniesienia: Sound in Webview i Error creating MediaPlayer with Uri or file in assets

Ale to nie działa.

Próbowałem za pomocą poniższych kodów, aby to zrobić:

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; 
     } 


    } 

} 

pojawia się niezdefiniowany błąd metody na metody getAssets(), próbowałem googleing go i mówi coś o przejściu do kontekstu. Jestem nowicjuszem w zakresie programowania Android i Object Oriented, więc zastanawiam się, czy jest to właściwy sposób i czy istnieje proste wyjaśnienie kontekstu. Dziękuję Ci.

Poniżej są moje kompletne kody:

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()); 
    } 


} 

EDIT

Więc kody działa dzięki https://stackoverflow.com/users/488241/squonk ale teraz pojawia się kolejny problem, zaktualizowałem MyWebViewClient do następujące:

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; 
     } 
    } 
} 

Ale dostaję java.io.FileNotFoundException, ścieżka wydaje się jednak. Wrzuciłem 2 pliki mp3 w aktywa/stron internetowych/dźwięki/1.mp3 i aktywa/stron internetowych/1.mp3 i stosować następujące kody html, aby go przetestować:

<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> 

Ale pojawia się następujący błąd na 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) 

Czy jest coś złego w sposobie, w jaki nazwałem plik? Dzięki, wcześniej.

SOLVED

Thx do sugestii Squonk za starałem następujące kody aby to działało i działa dobrze, dziękuję 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; 
     } 
    } 
} 

A html go przetestować:

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

choć nie pojawia się błąd, jeśli wielokrotnie kliknij go, ale to już inna kwestia: D jaki sposób można zamykać pytanie? >. <

Odpowiedz

3

Jeżeli wyrażasz MediaPLayer w MyWebViewClient, dodać następujące ...

public class MyWebViewClient extends WebViewClient{ 

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

    ... 
} 

Następnie dodać konstruktora MyWebViewClient następująco ...

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

Następnie w shouldOverrideUrlLoading(...) dostać swoje aktywa w następujący sposób ...

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

w twojej MainActivity ustawić WebViewClient przekazując this (który jest aktywny Context) w następujący sposób ...

webMain.setWebViewClient(new MyWebViewClient(this)); 

Powinieneś również zwrócić false z shouldOverrideUrlLoading(...), jeśli t adres URL kończy się na ".mp3" - oznacza to, że Twoja aplikacja obsługuje obiekty WebView, a aplikacja hosta nie powinna uruchamiać instancji przeglądarki zasobów.

EDIT: Aby odtwarzać pliki audio z katalogu aktywów, trzeba ustawić źródło danych inaczej - patrz odpowiedź na przyjętą play-audio-file-from-the-assets-directory.

Należy również zadzwonić pod numer mp.prepare(), zanim zadzwonisz pod numer mp.start().

+0

Wow, dziękuję, przynajmniej teraz biegnij, ty, panie, jesteś legendą ... czekaj na to .. dary! Ale gdy kliknę link 1 i 3, otrzymuję java.oi.FileNotFoundException, wydaje się, że ścieżka do linku jest błędna>.

+0

@RanggaWiratno: Zobacz EDIT na końcu mojej odpowiedzi. – Squonk

+0

Tak, faktycznie spróbowałem również następujących. Dodałem parametry na afd i dodałem mp.prepare() i afd.close() przed mp.start() po przeczytaniu tego http://droidapp.co.uk/?p=272 ale dziwna rzecz jest, nadal otrzymuję wyjątek java.io.FileNotFoundException, mimo że ścieżka jest właściwa. Próbowałem zinterpretować zawartość html, ale nadal nie mogę tego naprawić: File Asset
i Same Folder. Wrzuciłem 2 pliki do przetestowania w zasobach> strony internetowe> 1.mp3 i zasoby> strony internetowe> dźwięki> 1.mp3 –

Powiązane problemy