国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Android 集成Chrome 瀏覽器內(nèi)核 Crosswalk

Crosswalk 內(nèi)核的興起與消亡

Android 4.4 版本之前,使用的是基于 androidWebKit 的 WebView

但實(shí)際上,由于 Android 的碎片化問題(大量存在不同的 Android 系統(tǒng)版本,并且各個(gè)廠商對(duì)內(nèi)置應(yīng)用進(jìn)行定制化,有可能用的不是最新的瀏覽器內(nèi)核)。這就導(dǎo)致 WebView 在真實(shí)環(huán)境中對(duì) API 的支持根本無(wú)跡可尋,越發(fā)混亂。

Android 碎片化問題集中表現(xiàn)在下面幾個(gè)方面:

  • 設(shè)備繁多,硬件配置參差不棄,設(shè)備性能各異,差距很大
  • 品牌眾多,廠商標(biāo)準(zhǔn)不一致,定制化系統(tǒng)體驗(yàn)不同
  • 版本各異,國(guó)內(nèi)外系統(tǒng)環(huán)境差異巨大
  • 分辨率不統(tǒng)一,各種類型尺寸眾多

隨著混合開發(fā)的興起,前端對(duì) API 的支持程度和網(wǎng)頁(yè)的表現(xiàn)效果都有了更嚴(yán)格的要求,原生WebView 由于碎片化嚴(yán)重,API支持程度未知,容易引發(fā)很多意料之外的BUG。

這時(shí)候,就誕生了一些第三方瀏覽器內(nèi)核

從 Android 5.0 開始,Google 把 Chromium blink內(nèi)核 webview 作為 apk 單獨(dú)從系統(tǒng)抽離出去,可以在應(yīng)用市場(chǎng)(Google Play)上面接收安裝更新。應(yīng)用可以直接使用該webview內(nèi)核,Google也可以及時(shí)發(fā)布更新,不用再通過(guò)更新系統(tǒng)才能更新瀏覽器內(nèi)核,也避免部分了 Android 系統(tǒng)碎片化問題。

因此 Intel 的 Crosswalk 就停止維護(hù)了。然而由于國(guó)內(nèi)被墻,并沒有接入谷歌服務(wù),因此 騰訊X5 內(nèi)核 還流傳至今,并且被廣泛的應(yīng)用

集成原因

現(xiàn)在代的手機(jī)上,原生的 webkit 內(nèi)嵌的谷歌內(nèi)核版本并不是很統(tǒng)一,這就導(dǎo)致了有些手機(jī)支持的API到另一個(gè)手機(jī),又不支持了。為了達(dá)到體驗(yàn)一致,也方便測(cè)試,我建議在國(guó)內(nèi),盡量使用騰訊X5進(jìn)行替換,X5的API和原生的基本一致,僅需要改動(dòng)較小的部分。

那么corsswalk,一個(gè)包40M,是不是就毫無(wú)用處了呢?答案是否定的,crosswalk現(xiàn)在多用于集成到
智能設(shè)備中。智能設(shè)備的網(wǎng)絡(luò)不一定好用,更別說(shuō)安裝QQ微信了,而且即使安裝了,也不一定支持騰訊X5,因?yàn)楝F(xiàn)在還是有部分手機(jī)無(wú)法兼容X5轉(zhuǎn)而降級(jí)為原生瀏覽器內(nèi)核的。

集成方式

添加依賴

可以在項(xiàng)目根路徑下的 build.gradle 中添加,針對(duì)所有module

buildscript {	repositorities {		……	}}allprojects {    repositories {    	……        maven { url 'https://download.01.org/crosswalk/releases/crosswalk/android/maven2'}    }}

兩個(gè)位置的 repositories 的區(qū)別

  1. buildscript 里是 gradle 腳本執(zhí)行所需依賴,分別是對(duì)應(yīng)的 maven 庫(kù)和插件
  2. allprojects 里是項(xiàng)目本身需要的依賴

也可以僅在對(duì)應(yīng) module 的 build.gradle 中添加 respositories,然后再添加對(duì)應(yīng)依賴

android {}repositories {	maven { url 'https://download.01.org/crosswalk/releases/crosswalk/android/maven2'}}dependencies {    implementation 'org.xwalk:xwalk_core_library:23.53.589.4'}

注意:添加依賴后不可能一次就同步成功,需要多同步好幾次

申請(qǐng)權(quán)限

在 AndroidManifest.xml 中添加如下權(quán)限聲明

<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" />

開啟硬件加速

從Android3.0(API Level 11)開始,Android 2D渲染管道k開始支持硬件加速(默認(rèn)是關(guān)閉的)。

可以在 AndroidManifest.xml 中,為 Application 添加屬性,開啟全局硬件加速

<Application	……	android:hardwareAccelerated="true" >	……</Application>	

硬件加速執(zhí)行的所有的繪圖操作,都是使用GPU在 View 對(duì)象的畫布上來(lái)進(jìn)行的。因?yàn)閱⒂糜布铀贂?huì)增加資源的需求,因此這樣的應(yīng)用會(huì)占用更多的內(nèi)存。

為了讓應(yīng)用能申請(qǐng)使用更多的內(nèi)存,還需要添加一個(gè) largeHeap 屬性。機(jī)器的內(nèi)存限制,在/system/build.prop文件中配置的,例如

dalvik.vm.heapsize=128m  dalvik.vm.heapgrowthlimit=64m  

heapgrowthlimit 是一個(gè)普通應(yīng)用的內(nèi)存限制,用ActivityManager.getLargeMemoryClass() 獲得的值就是這個(gè)。而 heapsize 是在 manifest 中設(shè)置了 largeHeap=true 之后,可以使用最大內(nèi)存值。

習(xí)慣性的為應(yīng)用多申請(qǐng)一點(diǎn)內(nèi)存,可以使用如下代碼

<Application	……	android:hardwareAccelerated="true"	android:largeHeap="true" >	……</Application>	

布局文件

<?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=".MainActivity">    <org.xwalk.core.XWalkView        android:id="@+id/webview"        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>

測(cè)試代碼

XWResourceClient.java

public class XWResourceClient extends XWalkResourceClient {    private static final String TAG = "XWalkResourceClient";    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());        super.onReceivedSslError(view, callback, error);    }    @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);    }    @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;    }}

XWUIClient.java

public class XWUIClient extends XWalkUIClient {    private static final String TAG = "XWalkUIClient";    public XWUIClient(XWalkView view) {        super(view);    }    @Override    public void onPageLoadStarted(XWalkView view, String url) {        Log.i(TAG, "onPageLoadStarted " + url);        super.onPageLoadStarted(view, url);    }    @Override    public void onPageLoadStopped(XWalkView view, String url, LoadStatus status) {        Log.i(TAG, "onPageLoadStopped " + url + ", " + status.toString());        super.onPageLoadStopped(view, url, status);    }    @Override    public boolean onJsAlert(XWalkView view, String url, String message, XWalkJavascriptResult result) {        Log.i(TAG, "onJsAlert " + url + ", " + message);        return super.onJsAlert(view, url, message, result);    }    @Override    public boolean onJsConfirm(XWalkView view, String url, String message, XWalkJavascriptResult result) {        Log.i(TAG, "onJsConfirm " + url + ", " + message);        return super.onJsConfirm(view, url, message, result);    }    @Override    public boolean onJsPrompt(XWalkView view, String url, String message, String defaultValue, XWalkJavascriptResult result) {        Log.i(TAG, "onJsPrompt " + url + ", " + message);        return super.onJsPrompt(view, url, message, defaultValue, result);    }    @Override    public boolean onConsoleMessage(XWalkView view, String message, int lineNumber, String sourceId, ConsoleMessageType messageType) {        Log.i(TAG, "onConsoleMessage " + message + ", " + lineNumber + ", " + sourceId + ", " + messageType.toString());        return super.onConsoleMessage(view, message, lineNumber, sourceId, messageType);    }    @Override    public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) {        Log.i(TAG, "onShowCustomView " + requestedOrientation);        super.onShowCustomView(view, requestedOrientation, callback);    }    @Override    public void onShowCustomView(View view, CustomViewCallback callback) {        Log.i(TAG, "onShowCustomView");        super.onShowCustomView(view, callback);    }    @Override    public boolean onCreateWindowRequested(XWalkView view, InitiateBy initiator, ValueCallback<XWalkView> callback) {        Log.i(TAG, "onCreateWindowRequested");        return super.onCreateWindowRequested(view, initiator, callback);    }    @Override    public boolean onJavascriptModalDialog(XWalkView view, JavascriptMessageType type, String url, String message, String defaultValue, XWalkJavascriptResult result) {        Log.i(TAG, "onJavascriptModalDialog " + type.toString() + ", " + url + ", " + message + ", " + defaultValue);        return super.onJavascriptModalDialog(view, type, url, message, defaultValue, result);    }    @Override    public void onFullscreenToggled(XWalkView view, boolean enterFullscreen) {        Log.i(TAG, "onFullscreenToggled " + enterFullscreen);        super.onFullscreenToggled(view, enterFullscreen);    }    @Override    public void onHideCustomView() {        Log.i(TAG, "onHideCustomView");        super.onHideCustomView();    }    @Override    public void onIconAvailable(XWalkView view, String url, Message startDownload) {        Log.i(TAG, "onIconAvailable " + url + ", " + startDownload.toString());        super.onIconAvailable(view, url, startDownload);    }    @Override    public void onJavascriptCloseWindow(XWalkView view) {        Log.i(TAG, "onJavascriptCloseWindow");        super.onJavascriptCloseWindow(view);    }    @Override    public void onReceivedIcon(XWalkView view, String url, Bitmap icon) {        Log.i(TAG, "onReceivedIcon " + url);        super.onReceivedIcon(view, url, icon);    }    @Override    public void onReceivedTitle(XWalkView view, String title) {        Log.i(TAG, "onReceivedTitle " + title);        super.onReceivedTitle(view, title);    }    @Override    public void onRequestFocus(XWalkView view) {        Log.i(TAG, "onRequestFocus");        super.onRequestFocus(view);    }    @Override    public void onScaleChanged(XWalkView view, float oldScale, float newScale) {        Log.i(TAG, "onScaleChanged " + oldScale + ", " + newScale);        super.onScaleChanged(view, oldScale, newScale);    }    @Override    public void onUnhandledKeyEvent(XWalkView view, KeyEvent event) {        Log.i(TAG, "onUnhandledKeyEvent " + event.getAction() + ", " + event.getKeyCode());        super.onUnhandledKeyEvent(view, event);    }    @Override    public void openFileChooser(XWalkView view, ValueCallback<Uri> uploadFile, String acceptType, String capture) {        Log.i(TAG, "openFileChooser " + acceptType + ", " + capture);        super.openFileChooser(view, uploadFile, acceptType, capture);    }    @Override    public boolean shouldOverrideKeyEvent(XWalkView view, KeyEvent event) {        Log.i(TAG, "shouldOverrideKeyEvent " + event.getAction() + ", " + event.getKeyCode());        return super.shouldOverrideKeyEvent(view, event);    }    @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;    }}

MainActivity.java

public class MainActivity extends XWalkActivity {    private XWalkView webView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        webView = findViewById(R.id.webview);        // Crosswalk's APIs are not ready yet    }    @Override    protected void onXWalkReady() {        initSettings();        webView.setUIClient(new XWUIClient(webView));        webView.setResourceClient(new XWResourceClient(webView));        webView.addJavascriptInterface(new AppShell(this), AppShell.TAG);        webView.loadUrl("http://www.baidu.com");    }    @Override    public void onPointerCaptureChanged(boolean hasCapture) {    }    @Override    protected void onNewIntent(Intent intent) {        super.onNewIntent(intent);        if(isXWalkReady()) webView.onNewIntent(intent);    }    @Override    protected void onPause() {        super.onPause();        if(isXWalkReady()) {            webView.pauseTimers();            webView.onHide();        }    }    @Override    protected void onResume() {        super.onResume();        if(isXWalkReady()) {            webView.resumeTimers();            webView.onShow();        }    }    @Override    protected void onDestroy() {        super.onDestroy();        if(isXWalkReady()) {            webView.onDestroy();        }    }    @Override    public void onBackPressed() {        if(isXWalkReady()) {            XWalkNavigationHistory history = webView.getNavigationHistory();            if (history.canGoBack()) {                history.navigate(XWalkNavigationHistory.Direction.BACKWARD, 1);            } else {                super.onBackPressed();            }        } else {            super.onBackPressed();        }    }    /**     * 沒有允許定位的設(shè)置     */    public void initSettings() {        XWalkSettings webSettings = webView.getSettings();        //啟用JavaScript        webSettings.setJavaScriptEnabled(true);        //允許js彈窗alert等,window.open方法打開新的網(wǎng)頁(yè),默認(rèn)不允許        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);        //localStorage和sessionStorage        webSettings.setDomStorageEnabled(true);        //Web SQL Databases        webSettings.setDatabaseEnabled(true);        //是否可訪問Content Provider的資源,默認(rèn)值 true        webSettings.setAllowContentAccess(true);        /*        是否允許訪問文件系統(tǒng),默認(rèn)值 true        file:///androMSG_asset和file:///androMSG_res始終可以訪問,不受其影響         */        webSettings.setAllowFileAccess(true);        //是否允許通過(guò)file url加載的Javascript讀取本地文件,默認(rèn)值 false        webSettings.setAllowFileAccessFromFileURLs(true);        //是否允許通過(guò)file url加載的Javascript讀取全部資源(包括文件,http,https),默認(rèn)值 false        webSettings.setAllowUniversalAccessFromFileURLs(true);        //設(shè)置是否支持縮放        webSettings.setSupportZoom(false);        //設(shè)置內(nèi)置的縮放控件        webSettings.setBuiltInZoomControls(false);        /*         當(dāng)該屬性被設(shè)置為false時(shí),加載頁(yè)面的寬度總是適應(yīng)WebView控件寬度;         當(dāng)被設(shè)置為true,當(dāng)前頁(yè)面包含viewport屬性標(biāo)簽,在標(biāo)簽中指定寬度值生效,如果頁(yè)面不包含viewport標(biāo)簽,無(wú)法提供一個(gè)寬度值,這個(gè)時(shí)候該方法將被使用。         */        webSettings.setUseWideViewPort(false);        //縮放至屏幕大小        webSettings.setLoadWithOverviewMode(true);        //支持多窗口        webSettings.setSupportMultipleWindows(true);        /*        緩存模式        LOAD_CACHE_ONLY         不使用網(wǎng)絡(luò),只讀取本地緩存        LOAD_DEFAULT            根據(jù)cache-control決定是否從網(wǎng)絡(luò)上獲取數(shù)據(jù)        LOAD_NO_CACHE           不使用緩存,只從網(wǎng)絡(luò)獲取數(shù)據(jù)        LOAD_CACHE_ELSE_NETWORK 只要本地有,無(wú)論是否過(guò)期,或者no-cache,都使用緩存中的數(shù)據(jù)         */        webSettings.setCacheMode(XWalkSettings.LOAD_DEFAULT);        //設(shè)置是否加載圖片        webSettings.setLoadsImagesAutomatically(true);        //允許遠(yuǎn)程調(diào)試        XWalkPreferences.setValue("enable-javascript", true);        XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, true);    }}

生命周期

XWalk 內(nèi)核加載的生命周期

  1. 預(yù)加載 xwalk 內(nèi)核
  2. 將共享的XWalk內(nèi)核與當(dāng)前Activity綁定
public static void reserveReflectObject(Object object) {	String tag = (String)sReservedActivities.getLast();    Log.d("XWalkLib", "Reserve object " + object.getClass() + " to " + tag);    ((LinkedList)sReservedActions.get(tag)).add(new XWalkCoreWrapper.ReservedAction(object));}
  1. 在Activity中初始化XWalk內(nèi)核

  2. 解壓、激活、將內(nèi)核附著在Activity上

  3. 下載模式禁用
    下載模式和共享模式差不多,只是共享模式是把APK下載下來(lái)當(dāng)成一個(gè)應(yīng)用安裝到手機(jī)上,而下載模式干脆把APK下載到自己的私有目錄下,把所有的so文件、資源解壓出來(lái)保存到自己的內(nèi)部私有目錄下只供自己使用。

  4. 通過(guò)反射,api版本是否等于lib版本(mApiVersion == minLibVersion)

private boolean checkCoreVersion() {  Log.d("XWalkLib", "[Environment] SDK:" + VERSION.SDK_INT);     Log.d("XWalkLib", "[App Version] build:23.53.589.4, api:" + this.mApiVersion + ", min_api:" + this.mMinApiVersion);     try {         Class<?> clazz = this.getBridgeClass("XWalkCoreVersion");         String buildVersion = "";         try {             buildVersion = (String)(new ReflectField(clazz, "XWALK_BUILD_VERSION")).get();         } catch (RuntimeException var5) {         }         int libVersion = (Integer)(new ReflectField(clazz, "API_VERSION")).get();         int minLibVersion = (Integer)(new ReflectField(clazz, "MIN_API_VERSION")).get();         Log.d("XWalkLib", "[Lib Version] build:" + buildVersion + ", api:" + libVersion + ", min_api:" + minLibVersion);         if (XWalkEnvironment.isDownloadMode() && XWalkEnvironment.isDownloadModeUpdate() && !buildVersion.isEmpty() && !buildVersion.equals("23.53.589.4")) {             this.mCoreStatus = 8;             return false;         }         if (this.mMinApiVersion > libVersion) {             this.mCoreStatus = 3;             return false;         }         if (this.mApiVersion < minLibVersion) {             this.mCoreStatus = 4;             return false;         }     } catch (RuntimeException var6) {         Log.d("XWalkLib", "XWalk core not found");         this.mCoreStatus = 2;         return false;     }     Log.d("XWalkLib", "XWalk core version matched");     return true; }
  1. 打印出,當(dāng)前庫(kù)是基于ARM架構(gòu)編譯的。當(dāng)前設(shè)備是arm64-v8a,使用嵌入模式運(yùn)行
  2. 搭建環(huán)境、初始化內(nèi)核、初始化視圖,激活任務(wù)執(zhí)行完畢,開始在 SurfaceView 上進(jìn)行繪制。
函數(shù)用途
getBridgeXWalkUIClient 和 XWalkResourceClient 獲取反射的對(duì)象
shouldInterceptLoadRequest攔截請(qǐng)求,在這里可以使用緩存
onPageLoadStarted、onPageLoadStopped頁(yè)面加載開始、結(jié)束,可以用來(lái)做自定義定時(shí)器
onLoadStarted、onLoadStopped頁(yè)面中的元素加載開始和結(jié)束
onReceivedResponseHeaders處理接收的頭部
shouldOverrideUrlLoading用來(lái)處理意圖
doUpdateVisitedHistory更新訪問歷史記錄
onReceivedTitle收到標(biāo)題

遇到的問題

1. Crosswalk‘s APIs are not ready yet


首先, org.xwalk.core.XWalkView 控件,只能在 XWalkActivity 里,也就是當(dāng)前 Activity 必須繼承自 XWalkActivity。

對(duì) XWalkView 的設(shè)置,只能 onXWalkReady 里。

在 Activity 的生命周期函數(shù)中調(diào)用 XWalkView 的方法需要先判斷是否初始化完畢。

2. Mismatch of CPU Architecture


so分32位和64位!

理論上官方應(yīng)該提供2種包含不同so的aar包。一種是32位的另一種是64位,32位的aar中只包含x86和armeabi-v7a兩種so文件,同理64位的包中只包含x86_64和arm64-v8a兩種so文件。

由于arm64-v8a平臺(tái)能兼容32位的so文件、x86_64也能兼容32位的x86 so文件,在不考慮性能(暫時(shí)未知性能問題)的情況下就可以直接集成32位的aar包,可以大大減少安裝包的大小。

騰訊X5的話,是僅支持32位的。我猜測(cè) crosswalk 應(yīng)該也是這個(gè)問題,因此僅集成32位即可。

因此可以在 module 的 build.gradle 中添加如下內(nèi)容

android {	defaultConfig {	    ndk {	        abiFilters 'armeabi-v7a'	    }	}}

然后,再跟騰訊 X5 的做法一樣,在 src/mian/jniLibs/armeabi-v7a 目錄下,創(chuàng)建一個(gè)空的 so

3. 文件選擇的問題

在 HTML5 中共有 4 種選擇文件的方式,代碼如下

<label>下面是選擇文件</label><input type="file"  name="filename" /><label>下面是通過(guò)攝像頭獲取文件</label><input capture="camera" id="cameraFile" name="imgFile" type="file"><label>下面是打開攝像頭拍照</label><input accept="image/*" capture="camera" id="imgFile" name="imgFile" type="file"><label>下面是打開攝像頭錄像</label><input accept="video/*" capture="camera" id="videoFile" name="imgFile" type="file">

在 CrossWalk 中對(duì)應(yīng)的函數(shù)是 XWalkUIClient.java 中的 openFileChooser。如果主動(dòng)不觸發(fā)回調(diào)函數(shù),即為未選擇,那么內(nèi)部會(huì)一直處于等待的過(guò)程中,即使下一次點(diǎn)擊選擇文件,也不會(huì)有響應(yīng)。

public void openFileChooser(XWalkView view, ValueCallback<Uri> uploadFile, String acceptType, String capture) {	……}

獲取文件(文件、拍照、相冊(cè)、錄像)

序號(hào)acceptTypecapture含義
1false獲取文件
2true打開攝像頭獲取文件
3image/*true打開攝像頭拍照
4video/*true打開攝像頭錄像

實(shí)現(xiàn)大致邏輯(再細(xì)的代碼就不貼了,講個(gè)思路)

@Overridepublic void openFileChooser(XWalkView view, ValueCallback<Uri> uploadFile, String acceptType, String capture) {    Log.i(TAG, "openFileChooser " + acceptType + ", " + capture);    super.openFileChooser(view, uploadFile, acceptType, capture);    if ("true".equals(capture)) {        //判斷是拍視頻,還是拍照        boolean isVideo = "video/*".equals(acceptType);        String path;        DataCallback1<Uri> callback = uri -> {            LogUtil.i(TAG, "uri: " + (uri == null ? null : uri.toString()));            uploadFile.onReceiveValue(uri);        };        if (isVideo) {            //拍視頻            path = genMoviesPath(activity);            LogUtil.i(TAG, path);            if(path == null) return;            FileUtil.mkParentDirs(path);            LogUtil.d(TAG, "videoCapture: " + path);            IntentUtil.videoCapture(activity, path, callback);        } else {            //拍照片            path = genPicturePath(activity);            LogUtil.i(TAG, path);            if(path == null) return;            FileUtil.mkParentDirs(path);            LogUtil.d(TAG, "videoCapture: " + path);            IntentUtil.imageCaptureToUri(activity, path, callback);        }    } else {        if(TextUtils.isEmpty(acceptType)) acceptType = "*/*";        IntentUtil.selectFile(activity, acceptType, (uri, path, mimeType) -> uploadFile.onReceiveValue(uri));    }}

4. 注解 @JavascriptInterface

注意一個(gè)細(xì)節(jié),原生 webkit 乃至騰訊X5,用的都是 android.webkit.JavascriptInterface ,然而 crosswalk 不同,它用的是 org.xwalk.core.JavascriptInterface。如果注解用錯(cuò)了,抱歉 Uncaught TypeError: <JavaScriptInterfaceName.Method> is not a function

部分方法不支持

Object #<HTMLElement> has no method 'remove'

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Android調(diào)用默認(rèn)瀏覽器打開指定Url的方法實(shí)例
Android實(shí)例剖析筆記(三)
額外問題:onCreate中的savedInstanceState有何具體作用?具體例子?...
第二十九講:WebView學(xué)習(xí)指南 ? { Android學(xué)習(xí)指南 }
Android WebView 緩存處理
使用HTML5開發(fā)Android本地應(yīng)用
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服