【问题标题】:Android: Playing an Asset Sound Using WebViewAndroid:使用 WebView 播放资产声音
【发布时间】:2012-06-13 12:57:37
【问题描述】:

当用户单击我的应用程序 WebView 上的标签时,我正在尝试从资产文件夹播放声音。我发现我可以使用扩展 WebViewClient 的新类来检测链接的扩展名,如果它是 mp3 文件,它可以通过默认的音频播放器播放它。但我希望它在活动中播放而不开始新活动。

我使用以下链接作为参考: Sound in WebviewError creating MediaPlayer with Uri or file in assets

但是没有用。

我尝试使用以下代码:

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


    }

}

我在 getAssets() 上收到一个未定义的方法错误,我尝试用 Google 搜索它,它说明了有关传递上下文的信息。我对 Android 和面向对象编程非常陌生,所以我想知道这是否是正确的方法,以及是否有关于 Context 是什么的简单解释。谢谢。

以下是我的完整代码:

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


}

编辑

感谢https://stackoverflow.com/users/488241/squonk,代码可以正常工作,但现在又出现了另一个问题,我将 MyWebViewClient 更新为以下内容:

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

但我得到一个 java.io.FileNotFoundException,但路径似乎是正确的。我在 assets/webpages/sounds/1.mp3 和 assets/webpages/1.mp3 中放了 2 个 mp3 文件,并使用以下 html 代码对其进行测试:

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

但我在 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)

我调用文件的方式有问题吗?之前谢谢。

已解决

感谢 squonk 的建议,我尝试了以下代码使其正常工作,效果很好,谢谢 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;
        }   
    }
}

以及测试它的html:

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

虽然如果我反复单击它确实会出现错误,但这是另一个问题 :D 如何结束自己的问题? >.

【问题讨论】:

    标签: android audio webview android-assets


    【解决方案1】:

    如果您在 MyWebViewClient 中声明您的 MediaPLayer,请添加以下内容...

    public class MyWebViewClient extends WebViewClient{
    
        public MediaPlayer mp;
        private Context context = null; // Add this line
    
        ...
    }
    

    然后给MyWebViewClient添加一个构造函数如下...

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

    然后在shouldOverrideUrlLoading(...) 获取您的资产如下...

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

    在您的MainActivity 中,通过传递this(即活动Context)设置WebViewClient,如下所示...

    webMain.setWebViewClient(new MyWebViewClient(this));
    

    此外,如果 url 以“.mp3”结尾,您应该从 shouldOverrideUrlLoading(...) 返回 false - 这表明您的 WebView 正在处理事情,并且“主机”应用程序不应启动股票 Web 浏览器的实例。

    编辑:要播放资产目录中的音频文件,您需要以不同的方式设置数据源 - 请参阅play-audio-file-from-the-assets-directory 接受的答案。

    另外,您应该在拨打mp.start() 之前拨打mp.prepare()

    【讨论】:

    • 哇,谢谢它至少现在运行,您先生是传奇人物.. 等待它.. 亲爱的!但是,当我单击链接 1 和 3 时,它会收到 java.oi.FileNotFoundException,链接上的路径似乎是错误的 >.
    • @RanggaWiratno :请参阅答案末尾的编辑。
    • 是的,实际上我也尝试了以下方法。在阅读此droidapp.co.uk/?p=272 后,我在 afd 上添加了参数并在 mp.start() 之前添加了 mp.prepare() 和 afd.close() 但奇怪的是,我仍然得到 java.io.FileNotFoundException即使路径是正确的。我尝试弄乱 html,但仍然无法正确 File Asset
      同一文件夹。我在 assets>webpages>1.mp3 和 assets>webpages>sounds>1.mp3
      中放了 2 个文件来测试它
    • 我已经编辑了我的问题,希望它可以帮助你回答它,再次感谢:D
    • 是的,但不幸的是它也不起作用,我会尝试用其他一些类似的项目进行测试。好的,非常感谢嘿:D
    猜你喜欢
    • 2015-02-19
    • 1970-01-01
    • 1970-01-01
    • 2018-01-20
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-08
    相关资源
    最近更新 更多