admin管理员组

文章数量:1391987

I have a (customers) website that uses the js brightcove player to render html5 video. (read: I cannot edit the website itself)

In mobile Chrome the video works and everything is fine. However in my Android app, using a WebView that renders the exact same page cannot play the video.

I have read numerous similar SO questions and have made sure that the following is done:

  • turn off the web view plugins (to turn off Flash), in order to make sure that the html5 video is used and not the flash version.
  • javascript is obviously enabled
  • a webchromeclient is installed on the web view.
  • overwrite the onShowCustomView in the webchromeclient (unfortunately, it is never called)
  • hardware acceleration is turned on for the activity

Some posts suggest to call the play() method of the video manually, which imo is not a good idea, however, it is not possible anyway, as the video tag of the brightcove player is within an iframe and there is no way to obtain it via javascript.

By now I am running out of ideas, what or where the problem might be. Any suggestions are most appreciated. The only related log message in LogCat is:

10-25 14:01:01.503: D/VideoLayerManager(1307): Reinit GLResource for VideoLayer

MY WEBVIEW SETUP

Course content can be downloaded from here goo.gl/GVtgD0.

    webView = (WebView)findViewById(R.id.webView);
            webView.getSettings().setJavaScriptEnabled(true);
            webView.getSettings().setAllowFileAccess(true);
            webView.setSoundEffectsEnabled(true);
            webView.setWebChromeClient(new WebChromeClient());
            webView.loadUrl("file:///emulated/0/GA_nHanceK12/temp/class1-sub1-top2/index.html"));

LOGS FROM MY SIDE

07-16 14:44:11.787: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.787: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.787: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.797: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.797: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.797: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.807: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.807: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.817: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.817: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.817: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.817: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.827: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.827: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.837: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.837: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.837: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.847: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.847: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.847: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.857: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.857: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.857: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.857: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.857: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.867: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.867: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.867: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.867: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.917: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.917: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.917: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.917: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.927: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.927: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.927: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.927: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.927: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.937: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:12.488: D/VideoLayerManager(27539): Reinit GLResource for VideoLayer

I have a (customers) website that uses the js brightcove player to render html5 video. (read: I cannot edit the website itself)

In mobile Chrome the video works and everything is fine. However in my Android app, using a WebView that renders the exact same page cannot play the video.

I have read numerous similar SO questions and have made sure that the following is done:

  • turn off the web view plugins (to turn off Flash), in order to make sure that the html5 video is used and not the flash version.
  • javascript is obviously enabled
  • a webchromeclient is installed on the web view.
  • overwrite the onShowCustomView in the webchromeclient (unfortunately, it is never called)
  • hardware acceleration is turned on for the activity

Some posts suggest to call the play() method of the video manually, which imo is not a good idea, however, it is not possible anyway, as the video tag of the brightcove player is within an iframe and there is no way to obtain it via javascript.

By now I am running out of ideas, what or where the problem might be. Any suggestions are most appreciated. The only related log message in LogCat is:

10-25 14:01:01.503: D/VideoLayerManager(1307): Reinit GLResource for VideoLayer

MY WEBVIEW SETUP

Course content can be downloaded from here goo.gl/GVtgD0.

    webView = (WebView)findViewById(R.id.webView);
            webView.getSettings().setJavaScriptEnabled(true);
            webView.getSettings().setAllowFileAccess(true);
            webView.setSoundEffectsEnabled(true);
            webView.setWebChromeClient(new WebChromeClient());
            webView.loadUrl("file:///emulated/0/GA_nHanceK12/temp/class1-sub1-top2/index.html"));

LOGS FROM MY SIDE

07-16 14:44:11.787: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.787: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.787: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.797: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.797: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.797: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.807: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.807: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.817: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.817: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.817: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.817: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.827: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.827: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.837: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.837: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.837: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.847: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.847: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.847: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.857: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.857: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.857: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.857: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.857: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.867: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.867: D/MediaPlayer_Java(27539): [FXN.ASD] setDataSource :: uri = file:////storage/emulated/0/GA_nHanceK12/temp/class1-sub1-top2/_cp_n_m_
07-16 14:44:11.867: E/MediaPlayer-JNI(27539): [FXN][ASD]getVideoSurfaceTexture: null surface texture
07-16 14:44:11.867: E/MediaPlayer(27539): error (1, -2147483648)
07-16 14:44:11.917: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.917: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.917: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.917: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.927: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.927: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.927: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.927: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.927: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:11.937: E/MediaPlayer_Java(27539): Error (1,-2147483648)
07-16 14:44:12.488: D/VideoLayerManager(27539): Reinit GLResource for VideoLayer
Share Improve this question edited Jul 23, 2014 at 5:59 Nitin Misra 4,5223 gold badges35 silver badges52 bronze badges asked Oct 25, 2013 at 11:58 peshkirapeshkira 6,2491 gold badge34 silver badges48 bronze badges 6
  • Brightcove players work in this custom WebView, which implements the things you list above. If your player works with this you may be able to narrow down what you're missing. code.google./p/html5webview – misterben Commented Oct 25, 2013 at 12:36
  • Did you manage to solve this? – HyBRiD Commented Apr 30, 2014 at 8:47
  • You should setup a sample website that people can hit to give it a try. WebViews and video do not get along - especially when you throw javascript into the mix. I'm still looking for a reliable way to play video using JavaScript in all versions of Android. – Randy Commented Jul 16, 2014 at 18:33
  • Can you listen to the video and the screen is black? – dmarin Commented Jul 21, 2014 at 19:32
  • Chrome only became the default browser for the WebView in 4.4. So just because it works in mobile chrome does not mean it will work in all Android versions. Does it work in Android 4.4? Keep in mind you'll have to enable the correct settings for the webview. – Ali Commented Jul 22, 2014 at 7:02
 |  Show 1 more ment

3 Answers 3

Reset to default 2 +50

This answer might have an answer to your question.

I've tried with API 16 (4.1 JB) but this sample Brightcove video was played only when in fullscreen.

You could force-start the video in fullscreen mode and exit it when user asks to or when the video has finished.

I believe this is caused by the WebView class itself since 4.1 JellyBean was the transition from stock Android Browser to Google Chrome. While the default browser on newer 4.1 versions became Chrome, the WebViews however were still using the old engine and therefore were not able to properly render the videos.

Another solution would be to redirect the user and force him to use his browser (if you're lucky it's chrome and the video will be shown).

I hv worked on html5 video playing in android and this worked for me :

My Activity

public class Test extends Activity {

    HTML5WebView mWebView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mWebView = new HTML5WebView(this);

        if (savedInstanceState != null) {
            mWebView.restoreState(savedInstanceState);
        } else {    
            mWebView.loadUrl("http://player.vimeo./video/27244727");
        }

        setContentView(mWebView.getLayout());
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mWebView.saveState(outState);
    }

    @Override
    public void onStop() {
        super.onStop();
        mWebView.stopLoading();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (mWebView.inCustomView()) {
                mWebView.hideCustomView();
            //  mWebView.goBack();
                //mWebView.goBack();
                return true;
            }

        }
        return super.onKeyDown(keyCode, event);
    }
}

My Custom Webview

public class HTML5WebView extends WebView {

    private Context                             mContext;
    private MyWebChromeClient                   mWebChromeClient;
    private View                                mCustomView;
    private FrameLayout                         mCustomViewContainer;
    private WebChromeClient.CustomViewCallback  mCustomViewCallback;

    private FrameLayout                         mContentView;
    private FrameLayout                         mBrowserFrameLayout;
    private FrameLayout                         mLayout;

    static final String LOGTAG = "HTML5WebView";

    private void init(Context context) {
        mContext = context;     
        Activity a = (Activity) mContext;

        mLayout = new FrameLayout(context);

        mBrowserFrameLayout = (FrameLayout) LayoutInflater.from(a).inflate(R.layout.custom_screen, null);
        mContentView = (FrameLayout) mBrowserFrameLayout.findViewById(R.id.main_content);
        mCustomViewContainer = (FrameLayout) mBrowserFrameLayout.findViewById(R.id.fullscreen_custom_content);

        mLayout.addView(mBrowserFrameLayout, COVER_SCREEN_PARAMS);

        // Configure the webview
        WebSettings s = getSettings();
        s.setBuiltInZoomControls(true);
        s.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        s.setUseWideViewPort(true);
        s.setLoadWithOverviewMode(true);
      //  s.setSavePassword(true);
        s.setSaveFormData(true);
        s.setJavaScriptEnabled(true);
        mWebChromeClient = new MyWebChromeClient();
        setWebChromeClient(mWebChromeClient);

        setWebViewClient(new WebViewClient());

setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

        // enable navigator.geolocation 
       // s.setGeolocationEnabled(true);
       // s.setGeolocationDatabasePath("/data/data/org.itri.html5webview/databases/");

        // enable Web Storage: localStorage, sessionStorage
        s.setDomStorageEnabled(true);

        mContentView.addView(this);
    }

    public HTML5WebView(Context context) {
        super(context);
        init(context);
    }

    public HTML5WebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public HTML5WebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    public FrameLayout getLayout() {
        return mLayout;
    }

    public boolean inCustomView() {
        return (mCustomView != null);
    }

    public void hideCustomView() {
        mWebChromeClient.onHideCustomView();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if ((mCustomView == null) && canGoBack()){
                goBack();
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    private class MyWebChromeClient extends WebChromeClient {
        private Bitmap      mDefaultVideoPoster;
        private View        mVideoProgressView;

        @Override
        public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback)
        {
            //Log.i(LOGTAG, "here in on ShowCustomView");
            HTML5WebView.this.setVisibility(View.GONE);

            // if a view already exists then immediately terminate the new one
            if (mCustomView != null) {
                callback.onCustomViewHidden();
                return;
            }

            mCustomViewContainer.addView(view);
            mCustomView = view;
            mCustomViewCallback = callback;
            mCustomViewContainer.setVisibility(View.VISIBLE);
        }

        @Override
        public void onHideCustomView() {
            System.out.println("customview hideeeeeeeeeeeeeeeeeeeeeeeeeee");
            if (mCustomView == null)
                return;        

            // Hide the custom view.
            mCustomView.setVisibility(View.GONE);

            // Remove the custom view from its container.
            mCustomViewContainer.removeView(mCustomView);
            mCustomView = null;
            mCustomViewContainer.setVisibility(View.GONE);
            mCustomViewCallback.onCustomViewHidden();

            HTML5WebView.this.setVisibility(View.VISIBLE);
            HTML5WebView.this.goBack();
            //Log.i(LOGTAG, "set it to webVew");
        }


        @Override
        public View getVideoLoadingProgressView() {
            //Log.i(LOGTAG, "here in on getVideoLoadingPregressView");

            if (mVideoProgressView == null) {
                LayoutInflater inflater = LayoutInflater.from(mContext);
                mVideoProgressView = inflater.inflate(R.layout.video_loading_progress, null);
            }
            return mVideoProgressView; 
        }

         @Override
         public void onReceivedTitle(WebView view, String title) {
            ((Activity) mContext).setTitle(title);
         }

         @Override
         public void onProgressChanged(WebView view, int newProgress) {
             ((Activity) mContext).getWindow().setFeatureInt(Window.FEATURE_PROGRESS, newProgress*100);
         }

         @Override
         public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
             callback.invoke(origin, true, false);
         }
    }


    static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS =
        new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
}

custom_screen.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android./apk/res/android">
    <FrameLayout android:id="@+id/fullscreen_custom_content"
        android:visibility="gone"
        android:background="@color/black"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    />
    <LinearLayout android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout android:id="@+id/error_console"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
        />

        <FrameLayout android:id="@+id/main_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
        />
    </LinearLayout>
</FrameLayout>

video_loading_progress.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android./apk/res/android"
         android:id="@+id/progress_indicator"
         android:orientation="vertical"
         android:layout_centerInParent="true"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content">

       <ProgressBar android:id="@android:id/progress"
           style="?android:attr/progressBarStyleLarge"
           android:layout_gravity="center"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content" />

       <TextView android:paddingTop="5dip"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="center"
           android:text="loading_video" android:textSize="14sp"
           android:textColor="?android:attr/textColorPrimary" />
 </LinearLayout>

This may not help, but you should just download the source for Firefox for Android and bundle that into your app if it makes your life easier. I did this for a project where I needed websockets and we needed backward patibility.

本文标签: