简单说明
Crosswalk使用了Chromium内核,这意味着只能在Android 4.0以上才能使用,安卓4.4已经采用Chrominum内核,如果只是做简单的网页显示,原生的足够了,4.4以下的webkit内核有许多bug,各个版本不一致,api使用都有些不同(文件上传在4.4~4.4.2这之间的根本无解)。对于要做hybrid应用以及想解决平台一致性问题可以使用Crosswalk,但是牺牲的是apk的体积,集成Crosswalk体积至少要增大20M+(官方提供了shared模式,apk里不带runtime环境,首次运行时下载安装,可以自由配置下载地址)
开发方式一
如果要使用Crosswalk提供的开发方式,需要配置开发环境,并且后续的创建项目打包都是基于命令行形式的,适合不会Android的web开发人员使用,比如下面这些都需要安装
Java JDK
Apache Ant
Android SDK
NPM
Crosswalk App Tools
中文参考 官方文档
开发方式二 Embedding the Crosswalk Project
相当于嵌入一个WebView Using the embedding API is only recommended for cases where you have a substantial amount of Java code in your application, but want to write the UI (or parts of the UI) using web technologies.
XWalkView默认不能设置Visible和动画 XWalkView represents an Android view for web apps/pages. Thus most of attributes for Android view are valid for this class. Since it internally uses android.view.SurfaceView for rendering web pages by default, it can’t be resized, rotated, transformed and animated due to the limitations of SurfaceView. Alternatively, if the preference key ANIMATABLE_XWALK_VIEW
is set to True, XWalkView can be transformed and animated because TextureView is intentionally used to render web pages for animation support. Besides, XWalkView won’t be rendered if it’s invisible.
XWalkView需要开启硬件加速 XWalkView needs hardware acceleration to render web pages. As a result, the AndroidManifest.xml of the caller’s app must be appended with the attribute “android:hardwareAccelerated” and its value must be set as “true”.
1 2 <application android:name ="android.app.Application" android:label ="XWalkUsers" android:hardwareAccelerated ="true" >
注意生命周期的接管 Unlike other Android views, this class has to listen to system events like application life cycle, intents, and activity result. The web engine inside this view need to get and handle them. And the onDestroy() method of XWalkView MUST be called explicitly when an XWalkView won’t be used anymore, otherwise it will cause the memory leak from the native side of the web engine. It’s similar to the destroy() method of Android WebView. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 import android.app.Activity;import android.os.Bundle;import org.xwalk.core.XWalkResourceClient;import org.xwalk.core.XWalkUIClient;import org.xwalk.core.XWalkView;public class MyActivity extends Activity { XWalkView mXwalkView; class MyResourceClient extends XWalkResourceClient { MyResourceClient(XWalkView view) { super (view); } @Override WebResourceResponse shouldInterceptLoadRequest (XWalkView view, String url) { ... } } class MyUIClient extends XWalkUIClient { MyUIClient(XWalkView view) { super (view); } @Override void onFullscreenToggled (XWalkView view, String url) { ... } } @Override protected void onCreate (Bundle savedInstanceState) { mXwalkView = new XWalkView(this , null ); setContentView(mXwalkView); mXwalkView.setResourceClient(new MyResourceClient(mXwalkView)); mXwalkView.setUIClient(new MyUIClient(mXwalkView)); mXwalkView.load("http://www.crosswalk-project.org" , null ); } @Override protected void onPause () { super .onPause(); if (mXwalkView != null ) { mXwalkView.pauseTimers(); mXwalkView.onHide(); } } @Override protected void onResume () { super .onResume(); if (mXwalkView != null ) { mXwalkView.resumeTimers(); mXwalkView.onShow(); } } @Override protected void onDestroy () { super .onDestroy(); if (mXwalkView != null ) { mXwalkView.onDestroy(); } } @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) { if (mXwalkView != null ) { mXwalkView.onActivityResult(requestCode, resultCode, data); } } @Override protected void onNewIntent (Intent intent) { if (mXwalkView != null ) { mXwalkView.onNewIntent(intent); } } }
配置gradle
添加仓库1 2 3 4 5 6 repositories { mavenLocal() maven { url 'https://download.01.org/crosswalk/releases/crosswalk/android/maven2' } }
添加cpu配置1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 android { splits { abi { enable true reset() include 'x86' , 'armeabi-v7a' universalApk true } } productFlavors { armv7 { versionCode defaultConfig.versionCode + 2 ndk { abiFilters "armeabi-v7a" , "" } } x86 { versionCode defaultConfig.versionCode + 4 ndk { abiFilters "x86" , "" } } } }
添加XWalkview依赖1 compile 'org.xwalk:xwalk_core_library:18.48.477.13'
混淆配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 -keepclasseswithmembernames class * { native <methods>;} -keepattributes JNINamespace -keepattributes CalledByNative -keepattributes Annotation -keepattributes EnclosingMethod -keep class org .xwalk .{ *; } -keep interface org .xwalk .{ *; } -keep class com .example .extension .**{ *; } -keep class org .crosswalkproject .*{ *; } -keep class org .chromium .base .Native -keep class org .chromium .base .annotations .JNINamespace -keepclasseswithmembers class org .chromium . { @org .chromium.base.AccessedByNative <methods>; }-keepclasseswithmembers class org .chromium . { @org .chromium.base.Native <methods>; } -keep class org .chromium .** { native <methods>; } -keep class org .chromium .base .UsedBy #-keep @org .chromium .base .UsedBy class -keepclassmembers class * { @org .chromium.base.UsedBy *; }#-keep @org.chromium.base.annotations.JNINamespace class -keepclassmembers class * { @org .chromium.base.annotations.CalledByNative *; } -dontnote org.chromium.net.AndroidKeyStore -dontnote org.chromium.net.UrlRequest$ResponseHeadersMap -keep class org .chromium .ui .ColorPickerAdvanced { <methods>; } -keep class org .chromium .ui .ColorPickerMoreButton { <methods>; } -keep class org .chromium .ui .ColorPickerSimple { <methods>; }
1 2 3 4 @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) { xWalkView.onActivityResult(requestCode, resultCode, data); }
should be overridden into the class XWalkUIClient:
1 2 3 4 @Override public void openFileChooser (XWalkView view, final ValueCallback uploadFile, String acceptType, String capture) { uploadFile.onReceiveValue(null ); }
链接Link 大量sample Crosswalk Project — replacement of Android WebView. Integration problems
XWalkPreferences.setValue只能在XWalkView未初始化之前调用,全局性配置 操蛋的回退键问题
XWalkView会接管Activity的onKeyUp,默认返回键就是回退历史,但是没有提供接口去控制。导致,一个页面有输入框,弹出输入法后不是关闭输入法,而是直接回退历史记录。不明白为什么要这么设计 解决方案:重写dispatchKeyEvent,当发现是回退键按下直接返回false,扔给外层处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class XWalkViewEx extends XWalkView { public XWalkViewEx (Context context) { super (context); init(); } public XWalkViewEx (Context context, Activity activity) { super (context, activity); init(); } public XWalkViewEx (Context context, AttributeSet attrs) { super (context, attrs); init(); } private void init () { } @Override public boolean dispatchKeyEvent (KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN && event.getKeyCode() == KeyEvent.KEYCODE_BACK) { return false ; } return super .dispatchKeyEvent(event); } public static void iniConfig () { XWalkPreferences.setValue(XWalkPreferences.ANIMATABLE_XWALK_VIEW, true ); } }
1 2 3 4 5 6 7 8 @Override public boolean onKeyBack () { if (mXWalkView.getNavigationHistory().canGoBack()) { mXWalkView.getNavigationHistory().navigate(XWalkNavigationHistory.Direction.BACKWARD, 1 ); return true ; } return false ; }