Android:使用 WebView 播放资产声音 [英] Android: Playing an Asset Sound Using WebView
问题描述
当用户单击我的应用程序的 WebView 上的标签时,我试图从资产文件夹播放声音.我发现我可以使用一个扩展 WebViewClient 的新类来检测链接的扩展名,如果它是一个 mp3 文件,它可以通过默认的音频播放器播放它.但我希望它在不启动新活动的情况下在活动中播放.
I am trying to play a sound from the assets folder when a user clicks on an tag on my application's WebView. I found that I can use a new class extending WebViewClient to detect the extension of a link and if it is an mp3 file it can play it via the default Audio Player. But I want it to play within the activity without starting a new activity.
我使用以下链接作为参考:Webview 中的声音和 使用 Uri 或资产中的文件创建 MediaPlayer 时出错
I used the following links as references: Sound in Webview and Error creating MediaPlayer with Uri or file in assets
但是没有用.
我尝试使用以下代码来做到这一点:
I tried using the following codes to do so:
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 是什么的简单解释.谢谢.
I get an undefined method error on the getAssets(), I tried Googleing it and it says something about passing a Context. I am very new to Android and Object Oriented programming, so I am wondering if this the right way to do it and if there is a simple explanation on what a Context is. Thank you.
以下是我的完整代码:
MainActivity.class
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 更新为以下内容:
So the codes works thanks to https://stackoverflow.com/users/488241/squonk but now another problem occurs, I updated the MyWebViewClient into the following:
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,虽然路径似乎是正确的.我已经将 2 个 mp3 文件放在 assets/webpages/sounds/1.mp3 和 assets/webpages/1.mp3 中,并使用以下 html 代码对其进行测试:
But I get a java.io.FileNotFoundException, the path seems right though. I've put 2 mp3 files in assets/webpages/sounds/1.mp3 and assets/webpages/1.mp3 and used the following html codes to test it:
<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 上收到以下错误:
But I get the following error on 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)
我调用文件的方式有问题吗?先谢谢了.
Is there something wrong with the way I called the file? Thanks before.
已解决
感谢squonk的建议,我尝试了以下代码使其工作并且运行良好,谢谢squonk!
Thx to squonk's suggestions, I tried the following codes to make it work and it worked well, thank you 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如何结束一个人的问题?>.<
Though I did get an error if I repeatedly click it, but that's another question :D How does one close one's question? >.<
推荐答案
在 MyWebViewClient
中声明 MediaPLayer
的地方,添加以下内容...
Where you declare your MediaPLayer
in MyWebViewClient
, add the following...
public class MyWebViewClient extends WebViewClient{
public MediaPlayer mp;
private Context context = null; // Add this line
...
}
然后在MyWebViewClient
中添加一个构造函数,如下...
Then add a constructor to MyWebViewClient
as follows...
public MyWebViewClient(Context context) {
this.context = context;
}
然后在 shouldOverrideUrlLoading(...)
中获取您的资产如下...
Then in shouldOverrideUrlLoading(...)
get your assets as follows...
AssetFileDescriptor afd = context.getAssets().openFd(url);
在您的 MainActivity
中,通过传递 this
(即 Activity Context
)来设置 WebViewClient
,如下所示...
In your MainActivity
set the WebViewClient
by passing this
(which is the Activity Context
) as follows...
webMain.setWebViewClient(new MyWebViewClient(this));
如果 url 以.mp3"结尾,你也应该从 shouldOverrideUrlLoading(...)
返回 false
- 这会显示你的 WebView
正在处理事情,主机"应用程序不应启动股票网络浏览器的实例.
Also you should return false
from shouldOverrideUrlLoading(...)
if the url ends with '.mp3' - this shows your WebView
is handling things and the 'host' application should not start an instance of the stock web browser.
要播放资产目录中的音频文件,您需要以不同方式设置数据源 - 请参阅播放音频文件来自资产目录.
To play audio files from the assets directory, you need to set the data source differently - see the accepted answer to play-audio-file-from-the-assets-directory.
你也应该在调用 mp.start()
之前调用 mp.prepare()
.
Also you should call mp.prepare()
before calling mp.start()
.
这篇关于Android:使用 WebView 播放资产声音的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!