스마트기기개발관련/안드로이드 개발

android 안드로이드 버전 4.x 이상 버전에서 발생하는 WebView에서 동영상 재생시 전체화면모드에서 발생하는 오류 해결법 관련

AlrepondTech 2020. 9. 22. 19:39
반응형

 

 

 

 

=======================

=======================

=======================

 

 

 

 

 

 

 

 

Hi I created a webview app for my video site. The design of the site is a hybrid that loads for mobile users. Only videos compatible with mobile devices are loaded onto the hybrid. The players are from Vk, dailymotion, youtube, quicktime. The videos only play on sdk 11 and higher but when I click on the player button to go full screen it only stops the video from playing while never launching into full screen mode. I'm including as much code as I can in hopes someone can help me. I've googled this to death with no progress made. Any help would be greatly appreciated.

(Webviewactivity.java)

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(Window.FEATURE_PROGRESS);
    setContentView(R.layout.main);

    parentView = (RelativeLayout) findViewById(R.id.parent_rl);

    webviewProgress = (ProgressBar) findViewById(R.id.webview_progress);

    webview = (WebView) findViewById(R.id.webview);
    webview.getSettings().setJavaScriptEnabled(true);
    webview.getSettings().setBuiltInZoomControls(true);
    webview.getSettings().setAllowFileAccess(true);
    webview.setWebViewClient(new MyWebViewClient());
    webview.getSettings().setPluginState(WebSettings.PluginState.ON);
    webview.loadUrl(URL);
    webviewProgress.setProgress(0);

    webview.setWebChromeClient(new MyWebChromeClient());
    webview.setDownloadListener(new DownloadListener() {
        public void onDownloadStart(String url, String userAgent,
                String contentDisposition, String mimetype,
                long contentLength) {
            mProgressDialog = new ProgressDialog(WebViewActivity.this);
            mProgressDialog.setMessage("Downloading...");
            mProgressDialog.setIndeterminate(false);
            mProgressDialog.setMax(100);
            mProgressDialog
                    .setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            DownloadFile downloadFile = new DownloadFile();
            downloadFile.execute(url);
        }
    });

    initSlider();

    initAdmob();
}

/**
 * When when file was chosen
 */
@Override
protected void onActivityResult(int requestCode, int resultCode,
        Intent intent) {
    if (requestCode == FILECHOOSER_RESULTCODE) {
        if (null == mUploadMessage)
            return;
        Uri result = intent == null || resultCode != RESULT_OK ? null
                : intent.getData();
        mUploadMessage.onReceiveValue(result);
        mUploadMessage = null;

(Main.xml)

android:id="@+id/parent_rl"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:keepScreenOn="true" >

<ProgressBar
    android:id="@+id/webview_progress"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:maxHeight="5dip"
    android:minHeight="5dip"
    android:progressDrawable="@drawable/blueprogress" />

<FrameLayout
    android:id="@+id/framelayout"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/webview_progress"
    android:orientation="vertical" >

    <WebView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

(Manifest.xml)

package="com.wCHfree"
android:versionCode="7"
android:versionName="1.1" >

<uses-sdk
    android:minSdkVersion="11"
    android:targetSdkVersion="17" />

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

<application
    android:icon="@drawable/ic_launcher_red"
    android:label="@string/app_name"
    android:theme="@android:style/Theme.Black" >
    <activity
        android:name="com.webview.splashScreen.SplashScreenActivity"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name="com.webview.splashScreen.WebViewActivity"
        android:configChanges="orientation|screenSize|screenLayout"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
    </activity>
    <activity
        android:name="com.google.ads.AdActivity"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />

 

 

=======================

=======================

=======================

 

 

 

출처: http://plasticradio.tistory.com/415

 

안드로이드 4.0 이후에서는 WebView에서 유튜브나 플래시 동영상의 전체화면 모드 사용시 NullPointerException이 발생합니다. 이를 해결하기 위해서는 WebView에 WebChromeClient 를 설정해주어야 합니다. 

하지만 단순히 기본 WebChromeClient 객체를 생성하여 WebView에 설정할 경우 오류는 발생하지 않지만 영상이 정상적으로 재생이 안되는 문제가 있습니다. 

 

전체화면 모드가 제대로 작동되게 하려면 아래와 같이 WebChromeClient 클래스를 상속받은 클래스를 만든 후 이를 WebView에 설정하면 됩니다.


 

?

public class FullscreenableChromeClient extends WebChromeClient {
    protected Activity mActivity = null;


    private View mCustomView;
    private WebChromeClient.CustomViewCallback mCustomViewCallback;
    private int mOriginalOrientation;


    private FrameLayout mContentView;
    private FrameLayout mFullscreenContainer;


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


    public FullscreenableChromeClient(Activity activity) {
        this.mActivity = activity;
    }


    @Override
    public void onShowCustomView(View view, int requestedOrientation, WebChromeClient.CustomViewCallback callback) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            if (mCustomView != null) {
                callback.onCustomViewHidden();
                return;
            }


            mOriginalOrientation = mActivity.getRequestedOrientation();
            FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
            mFullscreenContainer = new FullscreenHolder(mActivity);
            mFullscreenContainer.addView(view, COVER_SCREEN_PARAMS);
            decor.addView(mFullscreenContainer, COVER_SCREEN_PARAMS);
            mCustomView = view;
            setFullscreen(true);
            mCustomViewCallback = callback;
            mActivity.setRequestedOrientation(requestedOrientation);
        }


        super.onShowCustomView(view, requestedOrientation, callback);
    }


    @Override
    public void onHideCustomView() {
        if (mCustomView == null) {
            return;
        }


        setFullscreen(false);
        FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
        decor.removeView(mFullscreenContainer);
        mFullscreenContainer = null;
        mCustomView = null;
        mCustomViewCallback.onCustomViewHidden();
        mActivity.setRequestedOrientation(mOriginalOrientation);
    }


    private void setFullscreen(boolean enabled) {
        Window win = mActivity.getWindow();
        WindowManager.LayoutParams winParams = win.getAttributes();
        final int bits = WindowManager.LayoutParams.FLAG_FULLSCREEN;
        if (enabled) {
            winParams.flags |= bits;
        } else {
            winParams.flags &= ~bits;
            if (mCustomView != null) {
                mCustomView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
            } else {
                mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
            }
        }
        win.setAttributes(winParams);
    }


    private static class FullscreenHolder extends FrameLayout {
        public FullscreenHolder(Context ctx) {
            super(ctx);
            setBackgroundColor(ctx.getResources().getColor(android.R.color.black));
        }


        @Override
        public boolean onTouchEvent(MotionEvent evt) {
            return true;
        }
    }
}

 

_mWebView.setWebChromeClient(new FullscreenableChromeClient(this));




출처 : http://stackoverflow.com/questions/12398565/android-ics-flash-webview-full-screen-throws-nullpointerexception

You need to implement showCustomView & hideCustomView method of WebChromeClient, also You need android:hardwareAccelerated="true" in your AndroidManifest File. I am posting my sample project here. What i have done is kept one Framelayout(customContainer) in my main.xml, and adding view received in showCustomView here, and removing it in onHide. Also hiding/showing webview accordingly. Below code works perfectly on device.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.webview"
          android:versionCode="1"
          android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher"
            android:hardwareAccelerated="true">
        <activity android:name="MyActivity"
                  android:configChanges="orientation|keyboardHidden"
                  android:hardwareAccelerated="true"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
        >
    <WebView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:id="@+id/webView"
            android:layout_gravity="center"
            />
    <FrameLayout
            android:id="@+id/customViewContainer"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:visibility="gone"
            />
</LinearLayout>

video_progress.xml

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

    <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"
              android:textSize="14sp"
              android:textColor="?android:attr/textColorPrimary"/>
</LinearLayout>

MyActivity.java

package com.example.webview;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;

public class MyActivity extends Activity {
    private WebView webView;
    private FrameLayout customViewContainer;
    private WebChromeClient.CustomViewCallback customViewCallback;
    private View mCustomView;
    private myWebChromeClient mWebChromeClient;
    private myWebViewClient mWebViewClient;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        customViewContainer = (FrameLayout) findViewById(R.id.customViewContainer);
        webView = (WebView) findViewById(R.id.webView);

        mWebViewClient = new myWebViewClient();
        webView.setWebViewClient(mWebViewClient);

        mWebChromeClient = new myWebChromeClient();
        webView.setWebChromeClient(mWebChromeClient);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setAppCacheEnabled(true);
        webView.getSettings().setBuiltInZoomControls(true);
        webView.getSettings().setSaveFormData(true);
        webView.loadUrl("http://m.youtube.com");
    }

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

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

    @Override
    protected void onPause() {
        super.onPause();    //To change body of overridden methods use File | Settings | File Templates.
        webView.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();    //To change body of overridden methods use File | Settings | File Templates.
        webView.onResume();
    }

    @Override
    protected void onStop() {
        super.onStop();    //To change body of overridden methods use File | Settings | File Templates.
        if (inCustomView()) {
            hideCustomView();
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {

            if (inCustomView()) {
                hideCustomView();
                return true;
            }

            if ((mCustomView == null) && webView.canGoBack()) {
                webView.goBack();
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

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

        @Override
        public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) {
           onShowCustomView(view, callback);    //To change body of overridden methods use File | Settings | File Templates.
        }

        @Override
        public void onShowCustomView(View view,CustomViewCallback callback) {

            // if a view already exists then immediately terminate the new one
            if (mCustomView != null) {
                callback.onCustomViewHidden();
                return;
            }
            mCustomView = view;
            webView.setVisibility(View.GONE);
            customViewContainer.setVisibility(View.VISIBLE);
            customViewContainer.addView(view);
            customViewCallback = callback;
        }

        @Override
        public View getVideoLoadingProgressView() {

            if (mVideoProgressView == null) {
                LayoutInflater inflater = LayoutInflater.from(MyActivity.this);
                mVideoProgressView = inflater.inflate(R.layout.video_progress, null);
            }
            return mVideoProgressView;
        }

        @Override
        public void onHideCustomView() {
            super.onHideCustomView();    //To change body of overridden methods use File | Settings | File Templates.
            if (mCustomView == null)
                return;

            webView.setVisibility(View.VISIBLE);
            customViewContainer.setVisibility(View.GONE);

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

            // Remove the custom view from its container.
            customViewContainer.removeView(mCustomView);
            customViewCallback.onCustomViewHidden();

            mCustomView = null;
        }
    }

    class myWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            return super.shouldOverrideUrlLoading(view, url);    //To change body of overridden methods use File | Settings | File Templates.
        }
    }

}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Thank you as well, that's a very authoritative answer. I will try it out, and if it's all good - the bounty is yours.– Andrew Weir Apr 25 '13 at 8:41 
I must say this example project works better than my own. I have videos working on 2.3.3 that wouldn't work on that version with my own project. Not even sure how you did that part. – digiboomz Apr 26 '13 at 9:11
Thanks for the great work you have done, quite simple way to handle webview video playing – Muhammad Babar May 14 '13 at 7:41
Many, many thanks. Best solution to showing HTML5 video I have found (and I have found a few..) – MichelNov 5 '13 at 15:28

 

 

 

 

반응형

 

728x90

 

 

 

 

=======================

=======================

=======================

 

 

 

 

출처 : http://stackoverflow.com/questions/12398565/android-ics-flash-webview-full-screen-throws-nullpointerexception

Android ICS Flash WebView full screen throws NullPointerException

My application uses a WebView to display flash video contents. 
Everything seems to go smoothly until you try to play full screen on Android ICS devices. 
It works fine on devices with lower version.
On ICS devices it throws a NullPointerException. Here is my code:

 webView.getSettings().setJavaScriptEnabled(true);
            webView.getSettings().setPluginsEnabled(true);
            webView.getSettings().setLoadWithOverviewMode(true);
            webView.getSettings().setUseWideViewPort(true);
            webView.setVerticalScrollbarOverlay(true);
            webView.setWebViewClient(new WebViewClient() {
                private ProgressDialog pd;

                @Override
                public void onPageStarted(WebView view, String url,
                        Bitmap favicon) {
                    pd = new ProgressDialog(TrainingDetailActivity.this);
                    pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                    pd.setMessage("Loading");
                    pd.show();
                    super.onPageStarted(view, url, favicon);
                }

                @Override
                public void onPageFinished(WebView view, String url) {
                    this.dismissDialog();
                    super.onPageFinished(view, url);
                }

                @Override
                public boolean shouldOverrideUrlLoading(WebView view,
                        String url) {
                    return false;
                }

                private void dismissDialog() {
                    if (pd != null) {
                        pd.dismiss();
                        pd = null;
                    }
                }
            });
            webView.loadDataWithBaseURL(baseUrl, htmlstr, "text/html", "utf-8", null);

After some digging, I found out that in ICS the android.webkit.PluginFullScreenHolder show() method gets called and throws an NullExceptionPointer. The problem lays there, not on my code. I tried some work around but none of them works.
- Work around : I added this line:

webView.setWebChromeClient(new WebChromeClient() );

With this work around the NullPointerException does not occur, but the video plays with no sound, and won't switch to Full screen mode.
I looked around stackoverflow for solutions, the closest which seems to solve my problem is this answer:
http://stackoverflow.com/a/9921073/1503155
But unfortunately the answerer didn't explain what is the variable base in his code snippet and I am still stuck.
My question is, is there a way to work around this bug. Is yes, How?
Thanks in advance.

 

My boss gave me permission to share this with you.

I had the same issue for a long time before cobbling this together.

Create this as a class, and set the chrome client of your WebView:

WebView.setWebChromeClient(...);

To this:

public class FullscreenableChromeClient extends WebChromeClient {
    protected Activity mActivity = null;

    private View mCustomView;
    private WebChromeClient.CustomViewCallback mCustomViewCallback;
    private int mOriginalOrientation;

    private FrameLayout mContentView;
    private FrameLayout mFullscreenContainer;

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

    public FullscreenableChromeClient(Activity activity) {
        this.mActivity = activity;
    }

    @Override
    public void onShowCustomView(View view, int requestedOrientation, WebChromeClient.CustomViewCallback callback) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            if (mCustomView != null) {
                callback.onCustomViewHidden();
                return;
            }

            mOriginalOrientation = mActivity.getRequestedOrientation();
            FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
            mFullscreenContainer = new FullscreenHolder(mActivity);
            mFullscreenContainer.addView(view, COVER_SCREEN_PARAMS);
            decor.addView(mFullscreenContainer, COVER_SCREEN_PARAMS);
            mCustomView = view;
            setFullscreen(true);
            mCustomViewCallback = callback;
            mActivity.setRequestedOrientation(requestedOrientation);
        }

        super.onShowCustomView(view, requestedOrientation, callback);
    }

    @Override
    public void onHideCustomView() {
        if (mCustomView == null) {
            return;
        }

        setFullscreen(false);
        FrameLayout decor = (FrameLayout) mActivity.getWindow().getDecorView();
        decor.removeView(mFullscreenContainer);
        mFullscreenContainer = null;
        mCustomView = null;
        mCustomViewCallback.onCustomViewHidden();
        mActivity.setRequestedOrientation(mOriginalOrientation);
    }

    private void setFullscreen(boolean enabled) {
        Window win = mActivity.getWindow();
        WindowManager.LayoutParams winParams = win.getAttributes();
        final int bits = WindowManager.LayoutParams.FLAG_FULLSCREEN;
        if (enabled) {
            winParams.flags |= bits;
        } else {
            winParams.flags &= ~bits;
            if (mCustomView != null) {
                mCustomView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
            } else {
                mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
            }
        }
        win.setAttributes(winParams);
    }

    private static class FullscreenHolder extends FrameLayout {
        public FullscreenHolder(Context ctx) {
            super(ctx);
            setBackgroundColor(ctx.getResources().getColor(android.R.color.black));
        }

        @Override
        public boolean onTouchEvent(MotionEvent evt) {
            return true;
        }
    }
}

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Thanks for upstairs' code

Host's problem I was encountered。

In Activity I resoled like that。

@Override
public void onBackPressed() {
    Log.e(TAG, "onBackPressed");

    if(mCustomView!=null){
        mFull.onHideCustomView();
    }else{
        super.onBackPressed();
    }
}

 

 

=======================

=======================

=======================

 

 

 

반응형