如何在 WebView 中内嵌播放 html5 视频?
我需要在 WebView 中内嵌播放 html5 视频。我发现了一种应该有效的技术,但它只是偶尔有效(见问题结尾)。当它不起作用时,不会调用 onShowCustomView。任何人都可以看到这不起作用的原因或建议替代方案吗?
package com.richcollins.VideoView;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.FrameLayout;
import android.widget.VideoView;
public class WebViewActivity extends Activity
{
WebView webView;
FrameLayout frameLayout;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflator = getLayoutInflater();
View inflatedView = inflator.inflate(R.layout.webview, null);
if (!(inflatedView instanceof FrameLayout))
{
throw new RuntimeException("inflated view not FrameLayout");
}
else
{
frameLayout = (FrameLayout)inflatedView;
}
setContentView(frameLayout);
webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setPluginState(WebSettings.PluginState.ON);
webView.setWebChromeClient(new MyWebChromeClient());
InputStream inputStream = getResources().openRawResource(R.raw.index);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
int readByte;
try
{
while((readByte = inputStream.read()) != -1)
{
outStream.write(readByte);
}
String html = outStream.toString("UTF8");
webView.loadDataWithBaseURL("http://localhost/index.html", html, "text/html", "utf-8", "http://localhost/index.html");
}
catch(Exception e)
{
throw new RuntimeException();
}
}
private class MyWebChromeClient extends WebChromeClient implements MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener {
VideoView videoView;
WebChromeClient.CustomViewCallback customViewCallback;
public void onProgressChanged(WebView view, int newProgress)
{
if (newProgress == 100)
{
view.loadUrl("javascript:playVideo()");
}
}
public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback)
{
customViewCallback = callback;
if (view instanceof FrameLayout){
FrameLayout videoFrameLayout = (FrameLayout) view;
if (videoFrameLayout.getFocusedChild() instanceof VideoView){
videoView = (VideoView) videoFrameLayout.getFocusedChild();
// hide the video controls
videoView.setMediaController(null);
//remove videoView from MediaPlayer and ad it to the content view
videoFrameLayout.removeView(videoView);
frameLayout.addView(videoView, ViewGroup.LayoutParams.WRAP_CONTENT);
videoView.setOnCompletionListener(this);
videoView.setOnErrorListener(this);
videoView.setOnPreparedListener(this);
videoView.start();
}
}
}
public void onPrepared(MediaPlayer mp)
{
}
public void onCompletion(MediaPlayer mp)
{
// this is needed to release the MediaPlayer and its resources so it can
// be used again later
videoView.stopPlayback();
// now remove the video and tell the callback to hide the custom view
frameLayout.removeView(videoView);
customViewCallback.onCustomViewHidden();
finish();
}
public boolean onError(MediaPlayer mp, int what, int extra)
{
return false; // we did not handle the error - onCompletion will be called
}
}
}
I need to play an html5 video inline in a WebView. I found a technique that is supposed to work, but it only works sporadically (see end of question). When it doesn't work, onShowCustomView isn't called. Can anyone see a reason that this isn't working or suggest an alternative?
package com.richcollins.VideoView;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.FrameLayout;
import android.widget.VideoView;
public class WebViewActivity extends Activity
{
WebView webView;
FrameLayout frameLayout;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflator = getLayoutInflater();
View inflatedView = inflator.inflate(R.layout.webview, null);
if (!(inflatedView instanceof FrameLayout))
{
throw new RuntimeException("inflated view not FrameLayout");
}
else
{
frameLayout = (FrameLayout)inflatedView;
}
setContentView(frameLayout);
webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setPluginState(WebSettings.PluginState.ON);
webView.setWebChromeClient(new MyWebChromeClient());
InputStream inputStream = getResources().openRawResource(R.raw.index);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
int readByte;
try
{
while((readByte = inputStream.read()) != -1)
{
outStream.write(readByte);
}
String html = outStream.toString("UTF8");
webView.loadDataWithBaseURL("http://localhost/index.html", html, "text/html", "utf-8", "http://localhost/index.html");
}
catch(Exception e)
{
throw new RuntimeException();
}
}
private class MyWebChromeClient extends WebChromeClient implements MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener {
VideoView videoView;
WebChromeClient.CustomViewCallback customViewCallback;
public void onProgressChanged(WebView view, int newProgress)
{
if (newProgress == 100)
{
view.loadUrl("javascript:playVideo()");
}
}
public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback)
{
customViewCallback = callback;
if (view instanceof FrameLayout){
FrameLayout videoFrameLayout = (FrameLayout) view;
if (videoFrameLayout.getFocusedChild() instanceof VideoView){
videoView = (VideoView) videoFrameLayout.getFocusedChild();
// hide the video controls
videoView.setMediaController(null);
//remove videoView from MediaPlayer and ad it to the content view
videoFrameLayout.removeView(videoView);
frameLayout.addView(videoView, ViewGroup.LayoutParams.WRAP_CONTENT);
videoView.setOnCompletionListener(this);
videoView.setOnErrorListener(this);
videoView.setOnPreparedListener(this);
videoView.start();
}
}
}
public void onPrepared(MediaPlayer mp)
{
}
public void onCompletion(MediaPlayer mp)
{
// this is needed to release the MediaPlayer and its resources so it can
// be used again later
videoView.stopPlayback();
// now remove the video and tell the callback to hide the custom view
frameLayout.removeView(videoView);
customViewCallback.onCustomViewHidden();
finish();
}
public boolean onError(MediaPlayer mp, int what, int extra)
{
return false; // we did not handle the error - onCompletion will be called
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
请参阅此,了解在 Web 视图中使用 HTML5 的 ICS 应用示例显示视频 - 希望它能解决您的问题。
如果你想“假”自动播放(在网络视图中被阻止),你将需要从页面 onload 事件触发 .play() 。如果您想处理播放列表,那么您将需要捕获并响应已结束的事件。
See this for an example of an ICS app that uses HTML5 within a webview to display a video - hopefully it will solve your issue.
if you want to "fake" autoplay (which is blocked in a webview) you will need to trigger the .play() from the page onload event. if you want to work through a playlist then you will need to trap and respond to the onended event.