【Android Web】騰訊X5瀏覽器的整合與常見問題

歡子發表於2019-02-27

前言

近年來,混合開發也越來越用的更多,而原生webview的各種坑,比如說 上傳圖片、檔案問題、視訊全屏問題(什麼在微信上開啟都是好的,你這怎麼全屏不了)、版本差異問題,所以還是建議使用騰訊x5瀏覽器。

如何使用

  • 1.去官網上下載最新的jar、so檔案等 連結點這裡
  • 2.新增jar包、so檔案,配置gradle
    QQ截圖20180728102235.png
    在build.gradle 中新增libs、配置ndk
 sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
複製程式碼
  ndk {
            abiFilters "armeabi"
        }
複製程式碼
  • 3.在Application中新增初始化x5程式碼,記得在AndroidManifest.xml中註冊你自定的Application
  QbSdk.PreInitCallback cb = new QbSdk.PreInitCallback() {

            @Override
            public void onViewInitFinished(boolean arg0) {
                //x5核心初始化完成的回撥,為true表示x5核心載入成功,否則表示x5核心載入失敗,會自動切換到系統核心。
                Log.d("app", " onViewInitFinished is " + arg0);
            }

            @Override
            public void onCoreInitFinished() {
            }
        };
        //x5核心初始化介面
        QbSdk.initX5Environment(getApplicationContext(), cb);
複製程式碼
  • 4.新增許可權

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_SETTINGS" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <!-- 硬體加速對X5視訊播放非常重要,建議開啟 -->
    <uses-permission android:name="android.permission.GET_TASKS" />
複製程式碼
  • 5.新增WebActivity,初始化x5配置 記得在AndroidManifest.xml中註冊
        webView = (WebView) findViewById(R.id.webView);
        WebSettings webSetting = webView.getSettings();
        webSetting.setJavaScriptEnabled(true);
        webSetting.setJavaScriptCanOpenWindowsAutomatically(true);
        webSetting.setAllowFileAccess(true);
        webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        webSetting.setSupportZoom(true);
        webSetting.setBuiltInZoomControls(false);
        webSetting.setUseWideViewPort(true);
        webSetting.setSupportMultipleWindows(true);
        // webSetting.setLoadWithOverviewMode(true);
        webSetting.setAppCacheEnabled(true);
        // webSetting.setDatabaseEnabled(true);
        webSetting.setDomStorageEnabled(true);
        webSetting.setGeolocationEnabled(true);
        webSetting.setAppCacheMaxSize(Long.MAX_VALUE);
        // webSetting.setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);
        webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);
        // webSetting.setRenderPriority(WebSettings.RenderPriority.HIGH);
        webSetting.setCacheMode(WebSettings.LOAD_NO_CACHE);

        getWindow().setFormat(PixelFormat.TRANSLUCENT);

        webView.getView().setOverScrollMode(View.OVER_SCROLL_ALWAYS);

        // this.getSettingsExtension().setPageCacheCapacity(IX5WebSettings.DEFAULT_CACHE_CAPACITY);//extension
        // settings 的設計
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView webView, String url) {
                webView.loadUrl(url);
                return true;
            }
        });
複製程式碼
  • 6、新增上傳檔案、圖片適配程式碼
  webView.setWebChromeClient(new WebChromeClient() {


            // For Android 3.0+
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
                uploadFile = uploadFile;
                openFileChooseProcess();
            }

            // For Android < 3.0
            public void openFileChooser(ValueCallback<Uri> uploadMsgs) {
                uploadFile = uploadFile;
                openFileChooseProcess();
            }

            // For Android  > 4.1.1
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                uploadFile = uploadFile;
                openFileChooseProcess();
            }

            // For Android  >= 5.0
            public boolean onShowFileChooser(com.tencent.smtt.sdk.WebView webView,
                                             ValueCallback<Uri[]> filePathCallback,
                                             WebChromeClient.FileChooserParams fileChooserParams) {
                uploadFiles = filePathCallback;
                openFileChooseProcess();
                return true;
            }

        });
複製程式碼

    private void openFileChooseProcess() {
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("*/*");
        startActivityForResult(Intent.createChooser(i, "test"), 0);
    }

複製程式碼
  • 7、處理選擇檔案、圖片後回撥
 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == RESULT_OK) {
            switch (requestCode) {
                case 0:
                    if (null != uploadFile) {
                        Uri result = data == null || resultCode != RESULT_OK ? null
                                : data.getData();
                        uploadFile.onReceiveValue(result);
                        uploadFile = null;
                    }
                    if (null != uploadFiles) {
                        Uri result = data == null || resultCode != RESULT_OK ? null
                                : data.getData();
                        uploadFiles.onReceiveValue(new Uri[]{result});
                        uploadFiles = null;
                    }
                    break;
                default:
                    break;
            }
        } else if (resultCode == RESULT_CANCELED) {
            if (null != uploadFile) {
                uploadFile.onReceiveValue(null);
                uploadFile = null;
            }

        }
    }
複製程式碼
  • 8、新增視訊全屏相關程式碼

        webView.setWebChromeClient(new WebChromeClient() {


            // For Android 3.0+
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
                uploadFile = uploadFile;
                openFileChooseProcess();
            }

            // For Android < 3.0
            public void openFileChooser(ValueCallback<Uri> uploadMsgs) {
                uploadFile = uploadFile;
                openFileChooseProcess();
            }

            // For Android  > 4.1.1
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                uploadFile = uploadFile;
                openFileChooseProcess();
            }

            // For Android  >= 5.0
            public boolean onShowFileChooser(com.tencent.smtt.sdk.WebView webView,
                                             ValueCallback<Uri[]> filePathCallback,
                                             WebChromeClient.FileChooserParams fileChooserParams) {
                uploadFiles = filePathCallback;
                openFileChooseProcess();
                return true;
            }

            View myVideoView;
            View myNormalView;
            IX5WebChromeClient.CustomViewCallback callback;


            /**
             * 全屏播放配置
             */
            @Override
            public void onShowCustomView(View view,
                                         IX5WebChromeClient.CustomViewCallback customViewCallback) {
                FrameLayout normalView = (FrameLayout) findViewById(R.id.web_filechooser);
                ViewGroup viewGroup = (ViewGroup) normalView.getParent();
                viewGroup.removeView(normalView);
                viewGroup.addView(view);
                myVideoView = view;
                myNormalView = normalView;
                callback = customViewCallback;
            }

            @Override
            public void onHideCustomView() {
                if (callback != null) {
                    callback.onCustomViewHidden();
                    callback = null;
                }
                if (myVideoView != null) {
                    ViewGroup viewGroup = (ViewGroup) myVideoView.getParent();
                    viewGroup.removeView(myVideoView);
                    viewGroup.addView(myNormalView);
                }
            }

        });
複製程式碼
 webView.addJavascriptInterface(new WebViewJavaScriptFunction() {

            @Override
            public void onJsFunctionCalled(String tag) {

            }

            @JavascriptInterface
            public void onX5ButtonClicked() {
                enableX5FullscreenFunc();
            }

            @JavascriptInterface
            public void onCustomButtonClicked() {
                disableX5FullscreenFunc();
            }

            @JavascriptInterface
            public void onLiteWndButtonClicked() {
                enableLiteWndFunc();
            }

            @JavascriptInterface
            public void onPageVideoClicked() {
                enablePageVideoFunc();
            }
        }, "Android");
複製程式碼
  // 向webview發出資訊
    private void enableX5FullscreenFunc() {

        if (webView.getX5WebViewExtension() != null) {
            Bundle data = new Bundle();

            data.putBoolean("standardFullScreen", false);// true表示標準全屏,false表示X5全屏;不設定預設false,

            data.putBoolean("supportLiteWnd", false);// false:關閉小窗;true:開啟小窗;不設定預設true,

            data.putInt("DefaultVideoScreen", 2);// 1:以頁面內開始播放,2:以全屏開始播放;不設定預設:1

            webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
                    data);
        }
    }

    private void disableX5FullscreenFunc() {
        if (webView.getX5WebViewExtension() != null) {
            Bundle data = new Bundle();

            data.putBoolean("standardFullScreen", true);// true表示標準全屏,會調起onShowCustomView(),false表示X5全屏;不設定預設false,

            data.putBoolean("supportLiteWnd", false);// false:關閉小窗;true:開啟小窗;不設定預設true,

            data.putInt("DefaultVideoScreen", 2);// 1:以頁面內開始播放,2:以全屏開始播放;不設定預設:1

            webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
                    data);
        }
    }

    private void enableLiteWndFunc() {
        if (webView.getX5WebViewExtension() != null) {
            Bundle data = new Bundle();

            data.putBoolean("standardFullScreen", false);// true表示標準全屏,會調起onShowCustomView(),false表示X5全屏;不設定預設false,

            data.putBoolean("supportLiteWnd", true);// false:關閉小窗;true:開啟小窗;不設定預設true,

            data.putInt("DefaultVideoScreen", 2);// 1:以頁面內開始播放,2:以全屏開始播放;不設定預設:1

            webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
                    data);
        }
    }

    private void enablePageVideoFunc() {
        if (webView.getX5WebViewExtension() != null) {
            Bundle data = new Bundle();

            data.putBoolean("standardFullScreen", false);// true表示標準全屏,會調起onShowCustomView(),false表示X5全屏;不設定預設false,

            data.putBoolean("supportLiteWnd", false);// false:關閉小窗;true:開啟小窗;不設定預設true,

            data.putInt("DefaultVideoScreen", 1);// 1:以頁面內開始播放,2:以全屏開始播放;不設定預設:1

            webView.getX5WebViewExtension().invokeMiscMethod("setVideoParams",
                    data);
        }
    }
複製程式碼
  • 9、新增下載相關程式碼
 webView.setDownloadListener(new DownloadListener() {
            @Override
            public void onDownloadStart(String s, String s1, String s2, String s3, long l) {

            }
        });
複製程式碼
  • 10、最後,當Activity銷燬時,釋放webview
 /**
     * 確保登出配置能夠被釋放
     */
    @Override
    protected void onDestroy() {
        if (this.webView != null) {
            webView.destroy();
        }
        super.onDestroy();
    }
複製程式碼

到這裡,x5瀏覽器的整合已經完成了,快去試試吧

常見問題

1.視訊無法全屏 請注意AndroidManifest.xml 中配置

 <activity
            android:name=".WebActivity"
            android:configChanges="orientation|screenSize|keyboardHidden"></activity>
複製程式碼

2.原生與webview 共享cookie 首先,原生需要將cookie 持久化的儲存起來,具體可以參考 【Android架構】基於MVP模式的Retrofit2+RXjava封裝之常見問題(四),至於非okhttp網路的,可以自行百度 然後傳遞給webview

      //建立CookieSyncManager
        CookieSyncManager.createInstance(context);
        //得到CookieManager
        CookieManager cookieManager = CookieManager.getInstance();
        cookieManager.setAcceptCookie(true);
        cookieManager.removeSessionCookie();// 移除
        cookieManager.removeAllCookie();
        //得到向URL中新增的Cookie的值
        store = new PersistentCookieStore(context);
        List<Cookie> cookieList = store.getCookies();
        if (cookieList != null && cookieList.size() > 0) {
            Cookie cookie = null;
         for (Cookie c : cookieList) {
                if (c.domain() != null) {
                    if (c.domain().contains("38")) {
                        cookie = c;
                    }
                }
            }
            if (cookie == null) {
                cookie = cookieList.get(0);
            }


            cookieManager.setCookie(url, cookie.name() + "=" + cookie.value());
          if (Build.VERSION.SDK_INT < 21) {
                CookieSyncManager.getInstance().sync();
            } else {
                CookieManager.getInstance().flush();
            }
        }
複製程式碼

需要注意的是,本地儲存的cookie可能會有多個,要根據domain 來判斷出正確的cookie

你的認可,是我堅持更新部落格的動力,如果覺得有用,就請點個贊,謝謝

相關文章