在 webview 中加载 flv 视频的问题
Posted
技术标签:
【中文标题】在 webview 中加载 flv 视频的问题【英文标题】:Problem to load flv video in webview 【发布时间】:2011-09-29 14:07:27 【问题描述】:我想在 webview 中加载 .flv 视频。
我得到了this link 的帮助,但问题是我无法在模拟器中观看视频。
这是我的代码:
package com.FlvTester;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
import android.widget.FrameLayout;
public class FlvTester extends Activity
WebView webView;
String htmlPre = "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\"></head><body style='margin:0; pading:0; background-color: black;'>";
String htmlCode =
" <embed style='width:100%; height:100%' src='http://www.platipus.nl/flvplayer/download/1.0/FLVPlayer.swf?fullscreen=true&video=@VIDEO@' " +
" autoplay='true' " +
" quality='high' bgcolor='#000000' " +
" name='VideoPlayer' align='middle'" + // width='640' height='480'
" allowScriptAccess='*' allowFullScreen='true'" +
" type='application/x-shockwave-flash' " +
" pluginspage='http://www.macromedia.com/go/getflashplayer' />" +
"";
String htmlPost = "</body></html>";
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webView = (WebView)findViewById(R.id.webview);
webView.getSettings().setjavascriptEnabled(true);
webView.getSettings().setAllowFileAccess(true);
webView.getSettings().setPluginsEnabled(true);
htmlCode = htmlCode.replaceAll("@VIDEO@", "file:///android_asset/expression_sad.flv");
webView.loadDataWithBaseURL("file:///android_asset/expression_sad.flv", htmlPre+htmlCode+htmlPost, "text/html", "UTF-8", null);
@Override
protected void onPause()
super.onPause();
callHiddenWebViewMethod("onPause");
webView.pauseTimers();
if(isFinishing())
webView.loadUrl("about:blank");
setContentView(new FrameLayout(this));
@Override
protected void onResume()
super.onResume();
callHiddenWebViewMethod("onResume");
webView.resumeTimers();
private void callHiddenWebViewMethod(String name)
// credits: http://***.com/questions/3431351/how-do-i-pause-flash- content-in-an-android-webview-when-my-activity-isnt-visible
if( webView != null )
try
Method method = WebView.class.getMethod(name);
method.invoke(webView);
catch (NoSuchMethodException e)
//Lo.g("No such method: " + name + e);
catch (IllegalAccessException e)
//Lo.g("Illegal Access: " + name + e);
catch (InvocationTargetException e)
//Lo.g("Invocation Target Exception: " + name + e);
我在 log cat 中遇到了这个错误
07-06 12:00:48.567: WARN/dalvikvm(381): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): FATAL EXCEPTION: main
07-06 12:00:48.597: ERROR/AndroidRuntime(381): java.lang.RuntimeException: Unable to start activity ComponentInfocom.FlvTester/com.FlvTester.FlvTester: java.lang.ClassCastException: android.widget.VideoView
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at android.os.Handler.dispatchMessage(Handler.java:99)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at android.os.Looper.loop(Looper.java:123)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at android.app.ActivityThread.main(ActivityThread.java:4627)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at java.lang.reflect.Method.invokeNative(Native Method)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at java.lang.reflect.Method.invoke(Method.java:521)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at dalvik.system.NativeStart.main(Native Method)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): Caused by: java.lang.ClassCastException: android.widget.VideoView
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at com.FlvTester.FlvTester.onCreate(FlvTester.java:31)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
07-06 12:00:48.597: ERROR/AndroidRuntime(381): ... 11 more
Main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_ android:layout_ xmlns:android="http://schemas.android.com/apk/res/android">
<WebView android:layout_ android:id="@+id/webview" android:layout_></WebView>
</LinearLayout>
更新
【问题讨论】:
好吧,不要试图在模拟器上玩flv或flash。他们永远无法播放这些格式。如果您有支持闪存的设备,请在上面尝试您的示例。它应该可以工作。 能否请您发布您的 main.xml 文件。 我的 main.xml 更新了,请注意 这很奇怪。 XML 指定了一个 WebView,您转换为一个 WebView,系统抱怨,因为它声称该视图是一个 VideoView。您绝对确定这是正在加载的main.xml
布局文件吗?也许你有一个 layout-portrait
或类似的资源文件夹和不同的 main.xml
?
@Ted Hopp 好的,现在我需要做什么
【参考方案1】:
这对我来说适用于本地 sdcard 文件
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.FrameLayout;
public class MainActivity extends Activity
private static final String TAG = "FLVplayer";
private static WebView webView;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
String file = "/sdcard/FLVplayer/20051210-w50s.flv";
String htmlPre = "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\"></head><body style='margin:0; pading:0; background-color: black;'>";
String htmlCode = " <embed style='width:100%; height:100%' src='/sdcard/FLVplayer/FLVPlayer.swf?fullscreen=true&video="
+ file
+ "&autoplay=true' "
+ " autoplay='true' "
+ " quality='high' bgcolor='#000000' "
+ " name='VideoPlayer' align='middle'"
+ // width='640' height='480'
" allowScriptAccess='*' allowFullScreen='true'"
+ " type='application/x-shockwave-flash' "
+ " pluginspage='http://www.macromedia.com/go/getflashplayer' />"
+ "";
String htmlPost = "</body></html>";
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webview);
// WebView webview = new WebView(this);
// setContentView(webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setAllowFileAccess(true);
webView.getSettings().setPluginState(WebSettings.PluginState.ON);
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED))
Log.d(TAG, "No SDCARD");
else
// load the content into the webview
// webView.loadUrl(htmlPre+htmlCode+htmlPost);
webView.loadDataWithBaseURL("file:///android_asset/FLVPlayer.swf",
htmlPre + htmlCode + htmlPost, "text/html", "UTF-8", null);
// sit back, watch FLV and eat popcorn
【讨论】:
【参考方案2】:我之前遇到过这个问题。问题是 load() 中的 URL 编码。您必须对 ?和 = 分别对应 URL 编码的等效 %3F 和 %3D。
【讨论】:
【参考方案3】:您没有明确说明您的 Android 版本是什么,但我可以确认 Flash 插件确实加载了,并且电影播放器确实使用了漩涡状图形。我可以让它进入全屏模式。我也可以播放在线视频,但不能从应用程序的资产文件夹播放,但我有一个解决方法。
manifest.xml 中需要以下许可:
<uses-permission android:name="android.permission.INTERNET"></uses-permission> <!-- where required -->
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
有趣的是,我发现我只能在静态加载 html 时从 assets 文件夹运行 SWF 播放器,即当我创建一个 html 文件并使用 loadUrl() 直接从 assets 文件夹加载它时。当使用 loadDataBaseUrl 方法加载 html 数据时,似乎有一些东西阻止了对应用程序目录的访问。
要成功从本地设备播放视频,需要一个静态 html 文件,并且视频必须位于 sdcard 上。我唯一的结论是,出于安全原因,assets 文件夹禁止使用嵌入式插件。
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
Log.d(TAG, "No SDCARD");
else
webView.loadUrl("file://"+Environment.getExternalStorageDirectory()+"/FLVplayer/index.html");
这里是html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body style="margin:0; pading:0; background-color: black;">
<embed
style="width:100%; height:100%"
src="./FLVPlayer.swf?fullscreen=true&video=./expression_sad.flv"
autoplay="true"
quality="high"
bgcolor="#000000"
name="VideoPlayer"
align="middle"
allowScriptAccess="*"
allowFullScreen="true"
type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer">
</embed>
</body>
</html>
这是一个 100% 有效的解决方案,但您必须在调用 loadUrl 以动态替换视频文件名之前将 html 文件写入 sdcard。此外,您应该将资产文件夹中的视频复制到 sdcard 上的相同路径中(正如您从我的示例中看到的那样,我创建了一个名为 FLVplayer 的文件夹。
在运行 Froyo(2.2) 的三星 Galaxy Tab 上进行的测试
更新
我包含了一个已经过测试和工作的完整活动。这需要将 Flash 播放器、FLV 文件和 index.html 文件的副本放在 sdcard 根目录上名为“FLVplayer”的文件夹中,您可以使用文件资源管理器复制该文件夹。您可以编辑各种实用程序函数来修改从资产文件夹复制文件的行为
package com.FLVplayer;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.webkit.WebView;
import android.widget.FrameLayout;
public class FLVplayerActivity extends Activity
private static final String TAG="FLVplayer";
private static WebView webView;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webView = (WebView)findViewById(R.id.webview);
//WebView webview = new WebView(this);
//setContentView(webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setAllowFileAccess(true);
webView.getSettings().setPluginsEnabled(true);
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
Log.d(TAG, "No SDCARD");
else
//prepare the directory
File flvDirectory = new File(Environment.getExternalStorageDirectory(),"FLVplayer");
if(!flvDirectory.exists())
try
flvDirectory.createNewFile();
catch (IOException e)
e.printStackTrace();
//specify the html file name to use
File flvHtml = new File(flvDirectory,"index.html");
//copy what you need
copySwfAsset(flvDirectory, "FLVPlayer.swf");
copyFlvAsset(flvDirectory, "20051210-w50s.flv");
//render the html
createVideoHtml(flvHtml, "20051210-w50s.flv");
//load the content into the webview
webView.loadUrl(Uri.fromFile(flvHtml).toString());
//sit back, watch FLV and eat popcorn
private void createVideoHtml(File htmlFile, String htmlFileName)
//TODO render your own html file to sdcard
private void copySwfAsset(File flvDirectory, String flashFileName)
//TODO copy your own SWF video player file from assets
private void copyFlvAsset(File flvDirectory, String videoFileName)
//TODO copy your oown FLV file from asset folder
@Override
protected void onPause()
super.onPause();
callHiddenWebViewMethod("onPause");
webView.pauseTimers();
if(isFinishing())
webView.loadUrl("about:blank");
setContentView(new FrameLayout(this));
@Override
protected void onResume()
super.onResume();
callHiddenWebViewMethod("onResume");
webView.resumeTimers();
private void callHiddenWebViewMethod(String name)
// credits: http://***.com/questions/3431351/how-do-i-pause-flash- content-in-an-android-webview-when-my-activity-isnt-visible
if( webView != null )
try
Method method = WebView.class.getMethod(name);
method.invoke(webView);
catch (NoSuchMethodException e)
//Lo.g("No such method: " + name + e);
catch (IllegalAccessException e)
//Lo.g("Illegal Access: " + name + e);
catch (InvocationTargetException e)
//Lo.g("Invocation Target Exception: " + name + e);
附录
我相信有一种方法可以绕过安全问题,方法是拦截各种文件的 URL,并使用 WebViewClient.shouldInterceptRequest() 直接从资产文件夹返回数据,但这需要 API 11,因此不适合作为通用解决方案。
【讨论】:
感谢您的回答。我试过你的答案,它显示请安装 adobe flush player 插件。那我该怎么办 我用这个synesthesia.it/playing-flash-flv-videos-in-android-applications链接播放flv视频。 flv 视频是在 HTC 而不是三星 Galaxy Ace 中播放的。所以然后我尝试了你的代码,它显示请安装 adobe 刷新播放器插件。请告诉我我必须改变什么。 你需要安装 adobe flash player ...我应该在 Galaxy Ace 上工作没有问题 我从 android 市场找到了 adobe flash player。当点击安装时,它显示 adobe flash player 已从 android 市场中删除。所以请给我下载adobe flash player的链接 好的,感谢您提供链接,但它没有安装在三星 Galaxy Ace 中。我不知道是什么问题。【参考方案4】:这里有一个快速提示。 我知道模拟器不支持闪存,许多廉价的安卓手机也不支持闪存。因此,当您进行测试时,请确保您在支持闪存的手机中进行测试。
【讨论】:
你是对的,但我也在手机中测试过,但无法成功。以上是关于在 webview 中加载 flv 视频的问题的主要内容,如果未能解决你的问题,请参考以下文章
Android:如何在 WebView 中加载 html 字符串?