Android整合三方瀏覽器之Crosswalk

ruomiz發表於2018-07-18

Android整合三方瀏覽器之Crosswalk

上一篇講解了騰訊 X5 核心的整合,這一篇是講解 Crosswalk 的整合 Crosswalk 也是採用了Chromenium 核心,是一款開源的 web 引擎,開發者可以直接把 Crosswalk 嵌入到應用之中,當然也支援共享模式(系統中沒有對應的 Crosswalk 庫是會提示下載)。只不過 Crosswalk 已經停止維護了。

Crosswalk官網

整合

想要使用 CrossWalk 有三種方式:

  1. maven 遠端依賴
//配置gradle
   repositories {
        maven {
            url 'https://download.01.org/crosswalk/releases/crosswalk/android/maven2'
        }
    }
複製程式碼
compile 'org.xwalk:xwalk_core_library:23.53.589.4'
複製程式碼

2.下載 zip 包後解壓,然後以用開發工具Import Module匯入,作為一個library依賴。

Android整合三方瀏覽器之Crosswalk
推薦使用stable(穩定版)!其他的分別是beta(測試版),canary(金絲雀版)。下載最新版本的zip包:23.53.589.4

3.下載aar 下載aar包後匯入專案的 lib目 錄下,然後在gradle中新增

repositories {
    flatDir {
        dirs 'libs'
    }
}
複製程式碼
compile(name: 'crosswalk-23.53.589.4', ext: 'aar')
複製程式碼

使用

1.manifest中新增

android:hardwareAccelerated="true" //application節點下開啟硬體加速
複製程式碼
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_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.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
複製程式碼

2.佈局中新增

    <org.xwalk.core.XWalkView
        android:id="@+id/xwalkview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </org.xwalk.core.XWalkView>
複製程式碼

3.新建 Activity 繼承 XWalkActivityonXWalkReady() 方法裡面進行初始化操作

class MainActivity : XWalkActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onXWalkReady() {
        XWalkPreferences.setValue(XWalkPreferences.ANIMATABLE_XWALK_VIEW, true);   //開啟預設動畫
        var setting = xwalkview.settings
        setting.loadWithOverviewMode = false
        setting.javaScriptEnabled = true                        //支援js
        setting.javaScriptCanOpenWindowsAutomatically = true    //支援通過JS開啟新視窗
        setting.useWideViewPort = true                          //將圖片調整到合適webview的大小
        setting.loadWithOverviewMode = true                     //縮放至螢幕的大小
        setting.loadsImagesAutomatically = true                 //支援自動載入圖片
        setting.supportMultipleWindows()                        //支援多視窗
        setting.setSupportZoom(true)
        setting.allowFileAccess = true
        setting.setDomStorageEnabled(true)
        setting.allowContentAccess = true
        setting.allowContentAccess = true
        setting.domStorageEnabled = true
        xwalkview.requestFocus()
        setting.cacheMode = WebSettings.LOAD_NO_CACHE
        xwalkview.setResourceClient(object : XWalkResourceClient(xwalkview) {
            override fun onLoadStarted(view: XWalkView?, url: String?) {
                super.onLoadStarted(view, url)
            }

            override fun onLoadFinished(view: XWalkView?, url: String?) {
                super.onLoadFinished(view, url)
            }

            override fun shouldOverrideUrlLoading(view: XWalkView?, url: String?): Boolean {
                view?.loadUrl(url)
                return true
            }

            override fun onReceivedSslError(view: XWalkView?, callback: 
                                            ValueCallback<Boolean>?, error: SslError?) {
                callback?.onReceiveValue(true)
                super.onReceivedSslError(view, callback, error)
            }


            override fun onReceivedLoadError(view: XWalkView?, errorCode: Int,
                                             description: String?, failingUrl: String?) {
                super.onReceivedLoadError(view, errorCode, description, failingUrl)
            }

            override fun onProgressChanged(view: XWalkView?, process: Int) {
                super.onProgressChanged(view, process)
                if (...) {
                    ...
                    progressBar.setProgress(process)
                    ...
                } else {
                    ...
                }
            }
        })
        xwalkview.setUIClient(object :XWalkUIClient(xwalkview){

            override fun onJsAlert(view: XWalkView?, url: String?, 
                                   	message: String?, result: XWalkJavascriptResult?): Boolean {
                return super.onJsAlert(view, url, message, result)
            }

            override fun onReceivedTitle(view: XWalkView?, title: String?) {
                super.onReceivedTitle(view, title)
            }

            override fun openFileChooser(view: XWalkView?, uploadFile: ValueCallback<Uri>?, acceptType: String?, capture: String?) {
                super.openFileChooser(view, uploadFile, acceptType, capture)
            }
        })

        xwalkview.loadUrl("your url")
    }
  
     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (xwalkview!=null){
            xwalkview.onActivityResult(requestCode, resultCode, data)
        }
    }

    override fun onNewIntent(intent: Intent?) {
        if (xwalkview != null) {
            xwalkview.onNewIntent(intent)
        }
    }
 
      override fun onDestroy() {
        super.onDestroy()
        XWalkPreferences.setValue(XWalkPreferences.ANIMATABLE_XWALK_VIEW, false);
    }
}
複製程式碼

XWalkUIClient 對應系統 webview 中的 WebChromeClient

XWalkResourceClient 對應系統 webviewWebViewClient

  • 監聽頁面生命
override fun onResume() {
    super.onResume()
    xwalkview?.let {
        xwalkview.pauseTimers()
        xwalkview.onHide()
    }
}
override fun onPause() {
    super.onPause()
    xwalkview?.let {
        xwalkview.pauseTimers()
        xwalkview.onHide()
    }
}
複製程式碼
  • 判斷頁面返回
if (xwalkview.navigationHistory.canGoBack()) {
    xwalkview.getNavigationHistory().navigate(
            XWalkNavigationHistory.Direction.BACKWARD, 1)
} else {
    finish()
}
複製程式碼

提示

在使用 Crosswalk 的過程遇到了幾個問題,在這裡提一下,希望能有一點幫助。

  1. lang.RuntimeException: Crosswalk's APIs are not ready yet異常:請在onready裡面進行相關設定和載入頁面
  2. 使用第一種 maven 整合方式 可能會報資源異常
    Android整合三方瀏覽器之Crosswalk
    在你的 build.gradle 中新增:
configurations.all {
    resolutionStrategy {
        force 'com.android.support:support-v4:27.1.0'//自己的版本號
    }
}
複製程式碼

3.Crosswalk 載入 SSL 證照有問題的網站時會報 Rquest was denied for security

override fun onReceivedSslError(view: XWalkView?, callback: ValueCallback<Boolean>?, error: SslError?) {
    callback?.onReceiveValue(true) //系統webview中的是handler.process()
}
複製程式碼

新增上述程式碼後會回撥 onReceivedLoadError並報net:: ERR_SECURITY_RESPONSE。這個問題折騰了很久,在 xwalkview的論壇 中發現 Crosswalk 會阻止連線到不信任的 SSL

最後發現原始碼中的 SsLUtil.java 會阻止載入。

public static boolean shouldDenyRequest(int error)
{
    assert error >= -215 && error <= -200;
    switch (error)
    {
        case -213:
        case -212:
        case -211:
        case -208:
        case -207:
        case -206:
        case -203:          
 //	case -202:   
        case -201:           
 //	case -200:  
    	case -150:
        case -129:
     return true;
    }
    return false;
}
複製程式碼

修改後的資源已忽略證照安全問題「不建議忽略證照安全問題,我是測試環境所需」

參考文件:

Crosswalk官網

Crosswalk Api 文件

Crosswalk 專案

官方論壇

最後

關於騰訊 X5 核心整合請跳轉:

Android整合三方瀏覽器之X5核心

相關文章