选择控件
- 原生Webview
- X5webView (腾讯内核)
- XWalkView(因特尔浏览器内核-----已停止维护)
我的结果
- 原生Webview(失败)
- X5webView (失败—但是使用QQ打开后可以使用)
- XWalkView(成功----目前只是用在Android5.1.1、Android6.0.1两版本测试成功;在Android10.0上不知道是什么原因失败------会增加apk体积40M或者20M)下载链接
代码
权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission
android:name="android.permission.CAPTURE_AUDIO_OUTPUT"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
a.引入依赖
//在app层级下build
implementation 'org.xwalk:xwalk_core_library:23.53.589.4'
//在工程的build
maven { url 'https://download.01.org/crosswalk/releases/crosswalk/android/maven2'}
//例如下面:
repositories {
google()
jcenter()
maven { url 'https://download.01.org/crosswalk/releases/crosswalk/android/maven2'}
}
allprojects {
repositories {
google()
jcenter()
maven { url 'https://download.01.org/crosswalk/releases/crosswalk/android/maven2'}
}
}
引入上面的依赖必须要配置证书(如果技术强大,自己编译一个跳过证书的)
b.可以下载aar包,引入经过更改跳过证书验证的aar。下载链接
代码
xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".WalkerXActivity">
<org.xwalk.core.XWalkView
android:id="@+id/xwalkView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
activity
package com.example.myapplication
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import org.xwalk.core.*
class WalkerXActivity : XWalkActivity() {
private var webView: XWalkView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_wal2)
webView = findViewById(R.id.xwalkView)
}
override fun onXWalkReady() {
initSettings()
webView?.setUIClient(XWUIClient(webView))
webView?.setResourceClient(XWResourceClient(webView))
//用来交互**加粗样式**
//webView?.addJavascriptInterface(new AppShell(this), AppShell.TAG);
webView?.loadUrl("http://www.baidu.com");
}
override fun onPointerCaptureChanged(hasCapture: Boolean) {}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
if (isXWalkReady) webView?.onNewIntent(intent)
}
override fun onPause() {
super.onPause()
if (isXWalkReady) {
webView?.pauseTimers()
webView?.onHide()
}
}
override fun onResume() {
super.onResume()
if (isXWalkReady) {
webView?.resumeTimers()
webView?.onShow()
}
}
override fun onDestroy() {
super.onDestroy()
if (isXWalkReady) {
webView?.onDestroy()
}
}
override fun onBackPressed() {
if (isXWalkReady) {
val history = webView?.navigationHistory
if (history?.canGoBack()!!) {
history.navigate(XWalkNavigationHistory.Direction.BACKWARD, 1)
} else {
super.onBackPressed()
}
} else {
super.onBackPressed()
}
}
/**
* 没有允许定位的设置
*/
@SuppressLint("SetJavaScriptEnabled")
fun initSettings() {
val webSettings = webView?.settings
//启用JavaScript
webSettings?.javaScriptEnabled = true
//允许js弹窗alert等,window.open方法打开新的网页,默认不允许
webSettings?.javaScriptCanOpenWindowsAutomatically = true
//localStorage和sessionStorage
webSettings?.domStorageEnabled = true
//Web SQL Databases
webSettings?.databaseEnabled = true
//是否可访问Content Provider的资源,默认值 true
webSettings?.allowContentAccess = true
/*
是否允许访问文件系统,默认值 true
file:///androMSG_asset和file:///androMSG_res始终可以访问,不受其影响
*/webSettings?.allowFileAccess = true
//是否允许通过file url加载的Javascript读取本地文件,默认值 false
webSettings?.allowFileAccessFromFileURLs = true
//是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https),默认值 false
webSettings?.allowUniversalAccessFromFileURLs = true
//设置是否支持缩放
webSettings?.setSupportZoom(false)
//设置内置的缩放控件
webSettings?.builtInZoomControls = false
/*
当该属性被设置为false时,加载页面的宽度总是适应WebView控件宽度;
当被设置为true,当前页面包含viewport属性标签,在标签中指定宽度值生效,如果页面不包含viewport标签,无法提供一个宽度值,这个时候该方法将被使用。
*/webSettings?.useWideViewPort = false
//缩放至屏幕大小
webSettings?.loadWithOverviewMode = true
//支持多窗口
webSettings?.setSupportMultipleWindows(true)
/*
缓存模式
LOAD_CACHE_ONLY 不使用网络,只读取本地缓存
LOAD_DEFAULT 根据cache-control决定是否从网络上获取数据
LOAD_NO_CACHE 不使用缓存,只从网络获取数据
LOAD_CACHE_ELSE_NETWORK 只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据
*/webSettings?.cacheMode = XWalkSettings.LOAD_DEFAULT
//设置是否加载图片
webSettings?.loadsImagesAutomatically = true
//允许远程调试
XWalkPreferences.setValue("enable-javascript", true)
XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, true)
}
}
自定义XWalkUIClient
package com.example.myapplication
import android.graphics.Bitmap
import android.net.Uri
import android.os.Message
import android.util.Log
import android.view.KeyEvent
import android.view.View
import android.webkit.ValueCallback
import org.xwalk.core.CustomViewCallback
import org.xwalk.core.XWalkJavascriptResult
import org.xwalk.core.XWalkUIClient
import org.xwalk.core.XWalkView
class XWUIClient(view: XWalkView?) : XWalkUIClient(view) {
override fun onPageLoadStarted(view: XWalkView, url: String) {
Log.i(TAG, "onPageLoadStarted $url")
super.onPageLoadStarted(view, url)
}
override fun onPageLoadStopped(
view: XWalkView,
url: String,
status: LoadStatus
) {
Log.i(
TAG,
"onPageLoadStopped $url, $status"
)
super.onPageLoadStopped(view, url, status)
}
override fun onJsAlert(
view: XWalkView,
url: String,
message: String,
result: XWalkJavascriptResult
): Boolean {
Log.i(TAG, "onJsAlert $url, $message")
return super.onJsAlert(view, url, message, result)
}
override fun onJsConfirm(
view: XWalkView,
url: String,
message: String,
result: XWalkJavascriptResult
): Boolean {
Log.i(TAG, "onJsConfirm $url, $message")
return super.onJsConfirm(view, url, message, result)
}
override fun onJsPrompt(
view: XWalkView,
url: String,
message: String,
defaultValue: String,
result: XWalkJavascriptResult
): Boolean {
Log.i(TAG, "onJsPrompt $url, $message")
return super.onJsPrompt(view, url, message, defaultValue, result)
}
override fun onConsoleMessage(
view: XWalkView,
message: String,
lineNumber: Int,
sourceId: String,
messageType: ConsoleMessageType
): Boolean {
Log.i(
TAG,
"onConsoleMessage $message, $lineNumber, $sourceId, $messageType"
)
return super.onConsoleMessage(view, message, lineNumber, sourceId, messageType)
}
override fun onShowCustomView(
view: View,
requestedOrientation: Int,
callback: CustomViewCallback
) {
Log.i(TAG, "onShowCustomView $requestedOrientation")
super.onShowCustomView(view, requestedOrientation, callback)
}
override fun onShowCustomView(
view: View,
callback: CustomViewCallback
) {
Log.i(TAG, "onShowCustomView")
super.onShowCustomView(view, callback)
}
override fun onCreateWindowRequested(
view: XWalkView,
initiator: InitiateBy,
callback: ValueCallback<XWalkView>
): Boolean {
Log.i(TAG, "onCreateWindowRequested")
return super.onCreateWindowRequested(view, initiator, callback)
}
override fun onJavascriptModalDialog(
view: XWalkView,
type: JavascriptMessageType,
url: String,
message: String,
defaultValue: String,
result: XWalkJavascriptResult
): Boolean {
Log.i(
TAG,
"onJavascriptModalDialog $type, $url, $message, $defaultValue"
)
return super.onJavascriptModalDialog(view, type, url, message, defaultValue, result)
}
override fun onFullscreenToggled(
view: XWalkView,
enterFullscreen: Boolean
) {
Log.i(TAG, "onFullscreenToggled $enterFullscreen")
super.onFullscreenToggled(view, enterFullscreen)
}
override fun onHideCustomView() {
Log.i(TAG, "onHideCustomView")
super.onHideCustomView()
}
override fun onIconAvailable(
view: XWalkView,
url: String,
startDownload: Message
) {
Log.i(
TAG,
"onIconAvailable $url, $startDownload"
)
super.onIconAvailable(view, url, startDownload)
}
override fun onJavascriptCloseWindow(view: XWalkView) {
Log.i(TAG, "onJavascriptCloseWindow")
super.onJavascriptCloseWindow(view)
}
override fun onReceivedIcon(
view: XWalkView,
url: String,
icon: Bitmap
) {
Log.i(TAG, "onReceivedIcon $url")
super.onReceivedIcon(view, url, icon)
}
override fun onReceivedTitle(view: XWalkView, title: String) {
Log.i(TAG, "onReceivedTitle $title")
super.onReceivedTitle(view, title)
}
override fun onRequestFocus(view: XWalkView) {
Log.i(TAG, "onRequestFocus")
super.onRequestFocus(view)
}
override fun onScaleChanged(
view: XWalkView,
oldScale: Float,
newScale: Float
) {
Log.i(TAG, "onScaleChanged $oldScale, $newScale")
super.onScaleChanged(view, oldScale, newScale)
}
override fun onUnhandledKeyEvent(
view: XWalkView,
event: KeyEvent
) {
Log.i(
TAG,
"onUnhandledKeyEvent " + event.action + ", " + event.keyCode
)
super.onUnhandledKeyEvent(view, event)
}
override fun openFileChooser(
view: XWalkView,
uploadFile: ValueCallback<Uri>,
acceptType: String,
capture: String
) {
Log.i(
TAG,
"openFileChooser $acceptType, $capture"
)
super.openFileChooser(view, uploadFile, acceptType, capture)
}
override fun shouldOverrideKeyEvent(
view: XWalkView,
event: KeyEvent
): Boolean {
Log.i(
TAG,
"shouldOverrideKeyEvent " + event.action + ", " + event.keyCode
)
return super.shouldOverrideKeyEvent(view, event)
}
override fun getBridge(): Any {
val obj = super.getBridge()
if (obj != null) {
Log.i(
TAG,
"getBridge " + obj.javaClass.simpleName
)
} else {
Log.i(TAG, "getBridge()")
}
return obj
}
companion object {
private const val TAG = "XWalkUIClient"
}
}
自定义XWResourceClient
package com.example.myapplication;
import android.net.http.SslError;
import android.util.Log;
import android.webkit.ValueCallback;
import android.webkit.WebResourceResponse;
import org.json.JSONObject;
import org.xwalk.core.ClientCertRequest;
import org.xwalk.core.XWalkHttpAuthHandler;
import org.xwalk.core.XWalkResourceClient;
import org.xwalk.core.XWalkView;
import org.xwalk.core.XWalkWebResourceRequest;
import org.xwalk.core.XWalkWebResourceResponse;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Map;
public class XWResourceClient extends XWalkResourceClient {
private static final String TAG = "XWalkUIClient";
public XWResourceClient(XWalkView view) {
super(view);
}
@Override
public void onLoadStarted(XWalkView view, String url) {
Log.i(TAG, "onLoadStarted " + url);
super.onLoadStarted(view, url);
}
@Override
public void onLoadFinished(XWalkView view, String url) {
Log.i(TAG, "onLoadFinished " + url);
super.onLoadFinished(view, url);
}
@Override
public void onProgressChanged(XWalkView view, int progressInPercent) {
Log.i(TAG, "onProgressChanged " + progressInPercent);
super.onProgressChanged(view, progressInPercent);
}
@Override
public boolean shouldOverrideUrlLoading(XWalkView view, String url) {
Log.i(TAG, "shouldOverrideUrlLoading " + url);
return super.shouldOverrideUrlLoading(view, url);
}
@Override
public WebResourceResponse shouldInterceptLoadRequest(XWalkView view, String url) {
Log.i(TAG, "shouldInterceptLoadRequest " + url);
return super.shouldInterceptLoadRequest(view, url);
}
@Override
public XWalkWebResourceResponse shouldInterceptLoadRequest(XWalkView view, XWalkWebResourceRequest request) {
Log.i(TAG, "shouldInterceptLoadRequest " + request.isForMainFrame() + ", " + request.getUrl() + ", " + new JSONObject(request.getRequestHeaders()).toString());
return super.shouldInterceptLoadRequest(view, request);
}
@Override
public void onReceivedSslError(XWalkView view, ValueCallback<Boolean> callback, SslError error) {
Log.i(TAG, "onReceivedSslError " + error.toString());
callback.onReceiveValue(true);
}
@Override
public void onReceivedLoadError(XWalkView view, int errorCode, String description, String failingUrl) {
Log.i(TAG, "onReceivedLoadError " + errorCode + ", " + description + ", " + failingUrl);
super.onReceivedLoadError(view, errorCode, description, failingUrl);
}
@Override
public void onDocumentLoadedInFrame(XWalkView view, long frameId) {
Log.i(TAG, "onDocumentLoadedInFrame " + frameId);
super.onDocumentLoadedInFrame(view, frameId);
}
@Override
public void onReceivedClientCertRequest(XWalkView view, ClientCertRequest handler) {
Log.i(TAG, "onReceivedClientCertRequest " + handler.getHost() + ", " + handler.getPort() + ", " + Arrays.toString(handler.getKeyTypes()));
super.onReceivedClientCertRequest(view, handler);
// handler.proceed();
}
@Override
public void onReceivedHttpAuthRequest(XWalkView view, XWalkHttpAuthHandler handler, String host, String realm) {
Log.i(TAG, "onReceivedHttpAuthRequest " + host + ", " + realm);
super.onReceivedHttpAuthRequest(view, handler, host, realm);
}
@Override
public void onReceivedResponseHeaders(XWalkView view, XWalkWebResourceRequest request, XWalkWebResourceResponse response) {
Log.i(TAG, "onReceivedResponseHeaders " + request.isForMainFrame() + ", " + request.getUrl() + ", " + new JSONObject(request.getRequestHeaders()).toString());
super.onReceivedResponseHeaders(view, request, response);
}
@Override
public XWalkWebResourceResponse createXWalkWebResourceResponse(String mimeType, String encoding, InputStream data) {
Log.i(TAG, "createXWalkWebResourceResponse " + mimeType + ", " + encoding);
return super.createXWalkWebResourceResponse(mimeType, encoding, data);
}
@Override
public XWalkWebResourceResponse createXWalkWebResourceResponse(String mimeType, String encoding,
InputStream data, int statusCode,
String reasonPhrase, Map<String, String> responseHeaders) {
Log.i(TAG, "createXWalkWebResourceResponse " + mimeType + ", " + encoding + ", " + statusCode + ", " + reasonPhrase + ", " + new JSONObject(responseHeaders));
return super.createXWalkWebResourceResponse(mimeType, encoding, data, statusCode, reasonPhrase, responseHeaders);
}
@Override
public void doUpdateVisitedHistory(XWalkView view, String url, boolean isReload) {
Log.i(TAG, "doUpdateVisitedHistory " + url + ", " + isReload);
super.doUpdateVisitedHistory(view, url, isReload);
}
@Override
protected Object getBridge() {
Object obj = super.getBridge();
if (obj != null) {
Log.i(TAG, "getBridge " + obj.getClass().getSimpleName());
} else {
Log.i(TAG, "getBridge()");
}
return obj;
}
}