在webview中加载flvvideo的问题
我想在webview中加载 .flvvideo。
我已经从这个链接的帮助,但问题是我无法在模拟器中查看video。
这是我的代码:
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://stackoverflow.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); } } } }
我在日志猫中得到这个错误
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 ComponentInfo{com.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_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <WebView android:layout_width="match_parent" android:id="@+id/webview" android:layout_height="match_parent"></WebView> </LinearLayout>
更新
你没有清楚地说明你的Android版本,但是我可以确认Flash插件确实加载了,而电影播放器却用旋涡状的graphics进行了修改。 我可以使其进入全屏模式。 我也能够播放在线video,但不能从应用程序的资产文件夹,但我有一个解决方法。
您的manifest.xml中需要以下许可证:
<uses-permission android:name="android.permission.INTERNET"></uses-permission> <!-- where required --> <uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
有趣的是,我发现只有当html静态加载时,我才能够从资源文件夹运行SWF播放器,也就是当我创build一个html文件,并使用loadUrl()从资源文件夹直接加载。 当使用loadDataBaseUrl方法加载html数据时,似乎阻止访问应用程序目录。
要成功地从本地设备播放video,必须将静态HTML文件和video共同放置在SD卡上。 我唯一的结论是,出于安全原因,资产文件夹对embedded式插件没有限制。
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%的工作解决scheme,但你必须在调用loadUrldynamicreplacevideo文件名之前,将你的html文件写入SD卡。 另外,您应该将资产文件夹中的video复制到SD卡上的相同path中(正如您从我的例子中看到的,我创build了一个名为FLVplayer的文件夹。
在三星Galaxy Tab运行Froyo(2.2)
UPDATE
我包括一个已经过testing和工作的完整活动。 这需要将Flash播放器,FLV文件和index.html文件的副本放在SD卡根目录下名为“FLVplayer”的文件夹中,您可以使用文件资源pipe理器复制该文件夹。 您可以编辑各种实用程序function来修改行为以从您的资源文件夹复制文件
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://stackoverflow.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); } } } }
ADENDUM
我相信有可能通过拦截各种文件的URL并使用WebViewClient.shouldInterceptRequest()直接从资产文件夹返回数据,但需要API 11,因此不适合作为通用解决scheme来绕过安全问题。
我之前遇到过这个问题。 问题是在load()中的URL编码。 你必须编码? 和=分别表示URL编码等效的%3F和%3D。
这是为我的本地SD卡文件
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 } } }
这是一个快速提示给你。 我知道模拟器不支持Flash,许多预算的Android手机也不支持Flash。 所以当你做testing的时候,一定要在支持闪光灯的手机上这样做。