第三方编辑网站怎么做,dw如何做网站界面,wordpress 说明书,安顺高端网站建设平台对于故乡#xff0c;我忽然有了新的理解#xff1a;人的故乡#xff0c;并不止于一块特定的土地#xff0c;而是一种辽阔无比的心情#xff0c;不受空间和时间的限制#xff1b;这心情一经唤起#xff0c;就是你已经回到了故乡。——《记忆与印象》 前言
移动互联网发展… 对于故乡我忽然有了新的理解人的故乡并不止于一块特定的土地而是一种辽阔无比的心情不受空间和时间的限制这心情一经唤起就是你已经回到了故乡。——《记忆与印象》 前言
移动互联网发展至今Android开发模式在不断更迭 目前主要有三种开发模式 原生开发、Hybrid开发以及跨平台开发。
原生开发 移动终端的开发主要分为两大阵营 Android(Java、Kotlin) 研发与 IOS(Swift)研发。Hybrid开发 多种技术栈混合开发App 在Android中主要指Native与前端(JavaScript)技术的混合开发方式。跨平台研发 同一个技术栈 同一套代码可以在不同的终端上运行极大的缩减了研发成本 比如当下比较火的Flutter。
首先我们需要做一些准备工作为应用添加一个启用了 JavaScript 的 WebView声明 INTERNET 权限WebView 需此权限才能加载页面即使页面内容为本地资源在 Assets 资源文件夹中放置页面并加载。
Layout ...WebViewandroid:idid/webviewandroid:layout_widthmatch_parentandroid:layout_heightmatch_parent/...XML
Manifest manifest ... uses-permission android:nameandroid.permission.INTERNET /.../manifestXML
MainActivity
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.webkit.WebView;...SuppressLint(SetJavaScriptEnabled)Overrideprotected void onCreate(Bundle savedInstanceState) {WebView mWebView findViewById(R.id.webview);mWebView.getSettings().setDefaultTextEncodingName(utf-8);mWebView.getSettings().setJavaScriptEnabled(true);mWebView.loadUrl(file:///android_asset/www/index.html); // You can directly use file://android_asset/ to load the files in the assets folder}...WebView H5 Hybrid混合开发基础知识
H5 Runtime支撑 - 浏览器内核
对于Java来说 最大的一个优点是build once run anywhere一处编译处处运行 这一优点主要是通过JVM在不同的平台解释执行在Android端使用的是基于JVM针对低性能小内存的设备优化的dalvik和art虚拟机。
对于前端技术栈来说 Runtime依赖浏览器的支持 浏览器主要依赖内核驱动内核的两个主要功能一个是界面渲染 一个是JavaScript 引擎JS语法解析当前的主流浏览器以及内核
浏览器渲染内核JS引擎IE/Edge微软Trident; EdgeHtmlJScript; ChakraSafari苹果Webkit/Webkit2JavaScripCore/Nitro(4)ChromeGoogleChromium(Webkit);BlinkV8FireFoxGeckoSpiderMonkey(❤️.0);TackMonkey(4.0);JaegerMonkey(4.0)OperaPresto;BlinkFuthark(9.5-10.2);CaraKan(10.5)
Chromium 是 Google 公司一个开源浏览器项目使用 Blink 渲染引擎V8 是 Blink 内置的JavaScript 引擎 Android端的WebView是基于Chromium的移动端浏览器组件。当前Android和IOS移动端的浏览器内核说到底都是基于Webkit。 WebKit主要分为四个部分
最上层 WebKit Embedding API 是 Browser UI 进行交互的 API 接口最下层 Platform API 提供与底层驱动的交互如网络字体渲染影音文件解码渲染引擎等WebCore 它实现了对文档的模型化包括了 CSS, DOM, Render 等的实现JSCore 是专门处理 JS 脚本的引擎, 以及Hybrid通信支持
WebKit 所包含的绘制引擎 和 JS引擎均是从KDE的KHTML及KJS引擎衍生而来。它们都是自由软件在GPL条约下授权同时支持BSD系统的开发。所以Webkit也是自由软件同时开放源代码。 KDE K桌面环境(K Desktop Environment)的缩写。一种著名的运行于 Linux、Unix 以及FreeBSD 等操作系统上的自由图形桌面环境 GNU 通用公共许可协议英语GNU General Public License缩写GNU GPL 或 GPL是被广泛使用的自由软件许可证给予了终端用户运行、学习、共享和修改软件的自由。 BSD Berkeley Software Distribution伯克利软件套件是Unix的衍生系统在1977至1995年间由加州大学伯克利分校开发和发布的。 JSBridge
JSBridge 是一座 Native 与 JavaScript 进行通讯的桥梁它的核心是 构建 Native 和 JavaScript 双向通信的通道。 所谓 双向通信的通道:
JS 向 Native 发送消息 : 调用相关功能、通知 Native 当前 JS 的相关状态等。Native 向 JS 发送消息 : 回溯调用结果、消息推送、通知 JS 当前 Native 的状态等。
JavascriptInterface
在 Android 和 Web 混合开发中免不了 Java 与 JavaScript 代码相互调用而 WebView 就给我们提供了这样一个接口JavascriptInterface public abstract interface JavascriptInterface implements Annotation Annotation that allows exposing methods to JavaScript. Starting from API level Build.VERSION_CODES.JELLY_BEAN_MR1 and above, only methods explicitly marked with this annotation are available to the Javascript code. 简单来说在 Android 4.2 Jelly BeanAPI 17后应用需要在方法中声明 JavascriptInterface 注解并将其所在类添加到 WebView 中允许应用内启用了 JavaScript 的 WebView 直接调用其类成员方法。
MainActivity
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import android.widget.Toast;...SuppressLint(StaticFieldLeak)private static Context mContext;SuppressLint(SetJavaScriptEnabled)Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mContext getApplicationContext();WebView mWebView findViewById(R.id.webview);mWebView.getSettings().setDefaultTextEncodingName(utf-8);mWebView.getSettings().setJavaScriptEnabled(true);mWebView.addJavascriptInterface(new JavaScriptBridge(), Android); // Export class JavaScriptBridge to WebView and map it to window.Android object in JavaScriptmWebView.loadUrl(file:///android_asset/www/index.html); // You can directly use file://android_asset/ to access the assets folder, or use file://android_res/ to access the res folder}SuppressWarnings(unused)public static class JavaScriptBridge {JavascriptInterfacepublic void makeToast(final String message) {Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();}}...WebPage
...
script typetext/javascriptuse strict;window.Android.makeToast(Hello world);
/script
...HTML
上述示例代码将允许 JavaScript 通过 window.Android 对象调用 JavaScriptBridge 类中声明了 JavascriptInterface 注解的 makeToast 方法。运行后显示一个内容为 Hello world 的 Toast。 链接访问拦截
WebViewClient 提供了 shouldOverrideUrlLoading 事件可以让我们在 URL 加载时做一些事情比如拦截某个链接。 public boolean shouldOverrideUrlLoading (WebView view, WebResourceRequest request) Give the host application a chance to take control when a URL is about to be loaded in the current WebView. If a WebViewClient is not provided, by default WebView will ask Activity Manager to choose the proper handler for the URL. If a WebViewClient is provided, returning true causes the current WebView to abort loading the URL, while returning false causes the WebView to continue loading the URL as usual. MainActivity
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;...SuppressLint(StaticFieldLeak)private static Context mContext;SuppressLint(SetJavaScriptEnabled)Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mContext getApplicationContext();WebView mWebView findViewById(R.id.webview);mWebView.getSettings().setDefaultTextEncodingName(utf-8);mWebView.getSettings().setJavaScriptEnabled(true);mWebView.setWebViewClient(new WebViewClient() {Overridepublic boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {if (request.getUrl().toString().equalsIgnoreCase(https://www.google.cn/)) {view.loadUrl(https://www.google.com/ncr);return true;} else if (request.getUrl().toString().startsWith(meowcat://open_settings)) {final Intent intent mContext.getPackageManager().getLaunchIntentForPackage(com.android.settings);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);mContext.startActivity(intent);return true;}return false;}});mWebView.loadUrl(file:///android_asset/www/index.html); // You can directly use file://android_asset/ to access the assets folder, or use file://android_res/ to access the res folder}...上述示例代码将在加载 https://www.google.cn/ 时跳转到 https://www.google.com/ncr*1或在链接为 meowcat://open_settings 时打开系统设置。
除示例代码外也可以直接 return true; 来中断页面加载。
注该方法不适用于 POST 请求页面在进行表单提交等 POST 请求时不会调用。 在页面内执行外部 JavaScript 代码
出于调试需求我们可能需要通过 Java 代码在页面内执行一些 JavaScript 代码使用 loadUrl(String) 或 evaluateJavascript(String, ValueCallbackString) 方法即可轻松实现该需求。若代码需要在页面加载完毕后执行WebViewClient 也为我们提供了 onPageFinished 事件。 public void loadUrl (String url) Loads the given URL. Also see compatibility note on evaluateJavascript(String, ValueCallback). public void evaluateJavascript (String script, ValueCallback resultCallback) Asynchronously evaluates JavaScript in the context of the currently displayed page. If non-null, resultCallback will be invoked with any result returned from that execution. This method must be called on the UI thread and the callback will be made on the UI thread. Compatibility note. Applications targeting Build.VERSION_CODES.N or later, JavaScript state from an empty WebView is no longer persisted across navigations like loadUrl(java.lang.String). For example, global variables and functions defined before calling loadUrl(java.lang.String) will not exist in the loaded page. Applications should use addJavascriptInterface(Object, String) instead to persist JavaScript objects across navigations. public void onPageFinished (WebView view, String url) Notify the host application that a page has finished loading. This method is called only for main frame. Receiving an onPageFinished() callback does not guarantee that the next frame drawn by WebView will reflect the state of the DOM at this point. In order to be notified that the current DOM state is ready to be rendered, request a visual state callback with WebView#postVisualStateCallback and wait for the supplied callback to be triggered. MainActivity
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;...SuppressLint(StaticFieldLeak)private static Context mContext;SuppressLint(SetJavaScriptEnabled)Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mContext getApplicationContext();WebView mWebView findViewById(R.id.webview);mWebView.getSettings().setDefaultTextEncodingName(utf-8);mWebView.getSettings().setJavaScriptEnabled(true);mWebView.setWebViewClient(new WebViewClient() {Overridepublic void onPageFinished(WebView view, String url) {if (url.startsWith(https://www.google.)) {view.loadUrl(javascript:(() {window.location https://www.google.com/ncr;})(););// Equals with// view.evaluateJavascript(window.location https://www.google.com/ncr;, null);}super.onPageFinished(view, url);}});mWebView.loadUrl(file:///android_asset/www/index.html); // You can directly use file://android_asset/ to access the assets folder, or use file://android_res/ to access the res folder}...上述示例代码将在页面加载完毕后打开 https://www.google.cn/而后被 shouldOverrideUrlLoading 方法跳转到 https://www.google.com/ncr。
代码中 loadUrl 与 evaluateJavascript 的示例等价选用其一即可。
注若使用 evaluateJavascript 方法的回调功能则此方法与回调方法都必须在主线程UI 线程中执行或声明。 本地资源加载
在上面的示例代码中我们使用了 file:///android_asset/ 来直接加载 assets 资源文件夹中的资源。但由于一些强制执行的安全策略Content Security Policy限制使得该非同源 URL 无法正常被加载这时候就可以使用 WebViewClient 提供的 shouldInterceptRequest 事件来辅助加载。 public WebResourceResponse shouldInterceptRequest (WebView view, WebResourceRequest request) Notify the host application of a resource request and allow the application to return the data. If the return value is null, the WebView will continue to load the resource as usual. Otherwise, the return response and data will be used. This callback is invoked for a variety of URL schemes (e.g., http(s):, data:, file:, etc.), not only those schemes which send requests over the network. This is not called for javascript: URLs, blob: URLs, or for assets accessed via file:///android_asset/ or file:///android_res/ URLs. In the case of redirects, this is only called for the initial resource URL, not any subsequent redirect URLs. MainActivity
import android.annotation.SuppressLint;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;import java.io.IOException;...SuppressLint(StaticFieldLeak)private static Context mContext;SuppressLint(SetJavaScriptEnabled)Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mContext getApplicationContext();WebView mWebView findViewById(R.id.webview);mWebView.getSettings().setDefaultTextEncodingName(utf-8);mWebView.getSettings().setJavaScriptEnabled(true);mWebView.addJavascriptInterface(new JavaScriptBridge(), Android); // Export class JavaScriptBridge to WebView and map it to window.Android object in JavaScriptmWebView.setWebViewClient(new WebViewClient() {Overridepublic void onPageFinished(WebView view, String url) {view.loadUrl(javascript:(() {const script document.createElement(script); script.src /MeowCat-Android-Asset/www/js/main.js; document.body.append(script);})(););super.onPageFinished(view, url);}Overridepublic WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest webResourceRequest) {String url webResourceRequest.getUrl().toString();Uri uri Uri.parse(url);String key uri.getScheme() :// uri.getHost() /MeowCat-Android-Asset/;if (url.contains(key)) {String assetsPath url.replace(key, );try {return new WebResourceResponse(text/plain, UTF-8, getAssets().open(assetsPath));} catch (IOException e) {e.printStackTrace();}}return super.shouldInterceptRequest(view, webResourceRequest);}});mWebView.loadUrl(https://www.google.com/ncr);}SuppressWarnings(unused)private static class JavaScriptBridge {JavascriptInterfacepublic void makeToast(final String message) {Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();}}...Main
use strict;
window.Android.makeToast(Hello world);JavaScript
上述示例代码将打开 https://www.google.com/ncr因 shouldInterceptRequest 方法不会在加载特殊 Schemes 时被调用故选用 Google 作为示例页面加载完毕后插入 script 标签加载并执行位于 file://android_asset/www/js/main.js 中的代码。运行后显示一个内容为 Hello world 的 Toast。
注在 Android 官方开发文档 中还有另一种使用 WebViewAssetLoader 的本地资源加载方式感兴趣的可以自行研究一下本文不再赘述。 JavaScript 弹窗提示
上面的示例代码已经可以帮助我们完成大多数需求但在实际应用中发现了另外一个问题JavaScript 的 alert() comfirm() prompt() 函数全部失效这不是我们期望的行为。WebChromeClient 为我们提供了 onJsAlert onJsConfirm onJsPrompt 事件分别对应上述函数我们需要自行实现上述方法。
MainActivity
import androidx.appcompat.app.AlertDialog;import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebView;...SuppressLint(StaticFieldLeak)private static Context mContext;SuppressLint(SetJavaScriptEnabled)Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mContext getApplicationContext();WebView mWebView findViewById(R.id.webview);mWebView.getSettings().setDefaultTextEncodingName(utf-8);mWebView.getSettings().setJavaScriptEnabled(true);mWebView.setWebChromeClient(new WebChromeClient() {Overridepublic boolean onJsAlert(WebView view, String url, String message, final JsResult result) {onJsDialog(DialogType.ALERT, view, url, message, result, null, null);return true;}Overridepublic boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {onJsDialog(DialogType.CONFIRM, view, url, message, result, null, null);return true;}Overridepublic boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) {onJsDialog(DialogType.PROMPT, view, url, message, null, defaultValue, result);return true;}});mWebView.loadUrl(file:///android_asset/www/index.html); // You can directly use file://android_asset/ to access the assets folder, or use file://android_res/ to access the res folder}private enum DialogType {ALERT,CONFIRM,PROMPT}private static void onJsDialog(DialogType type, WebView view, String url, String message, final JsResult result, String defaultValue, final JsPromptResult promptResult) {AlertDialog.Builder builder new AlertDialog.Builder(view.getContext());String[] content message.split(:, 2);builder.setTitle(content[0]);builder.setMessage(content[1] \n url);builder.setCancelable(false);switch (type) {case PROMPT:builder.setPositiveButton(android.R.string.ok, (dialog, which) - promptResult.confirm(defaultValue)); // TODO: Inputbreak;case CONFIRM:builder.setCancelable(true);builder.setNegativeButton(android.R.string.cancel, (dialog, which) - result.cancel());case ALERT:default:builder.setPositiveButton(android.R.string.ok, (dialog, which) - result.confirm());}builder.create().show();}...HTML
...
script typetext/javascriptuse strict;alert(Alert Title:This is an alert);confirm(Confirm Title:This is a confirm) ? alert(Alert Title (Confirm):You confirmed the dialog) : alert(Alert Title (Confirm):You canceled the dialog);alert(Alert Title (Prompt):Prompt content is prompt(Prompt Title:This is a prompt, Hello world));
/script
...HTML
上述示例代码中onJsDialog 方法统一处理了来自 WebChromeClient 的 onJsAlert onJsConfirm onJsPrompt 事件添加了标题JavaScript 函数仅支持信息传参这里以第一个 : 作为标题和信息的分隔符弹出对话框并返回DialogType 用于判断事件类型。
运行后依次弹出对话框内容分别为
Alert Title
This is an alert
file:///android_asset/www/index.html[OK]
Confirm Title
This is a confirm
file:///android_asset/www/index.html[CANCEL] [OK]若点击了 OK
Alert Title (Confirm)
You confirmed the dialog
file:///android_asset/www/index.html[OK]若点击了 CANCEL
Alert Title (Confirm)
You canceled the dialog
file:///android_asset/www/index.html[OK]
Prompt Title
This is a prompt
file:///android_asset/www/index.html[OK]
Alert Title (Prompt)
Prompt content is Hello world
file:///android_asset/www/index.html[OK]亦可根据其他需求定制对话框的样式和或功能。
注onJsDialog 方法仅作为示例并未实现 prompt() 函数的输入功能以默认值返回。 实战在页面中插入 vConsole 并在成功插入后弹出提示对话框
vConsole 是腾讯出品的一个轻量、可拓展、针对手机网页的前端开发者调试面板可以在 Vue、React 或其他任何框架中使用。用于移动设备调试非常好用下面的实例将使用本文所介绍的所有技巧在页面底部插入 vConsole。
下载 vconsole.min.js 并保存至 assets 资源文件夹中https://cdn.jsdelivr.net/npm/vconsolelatest/dist/vconsole.min.js
Java
import androidx.appcompat.app.AlertDialog;import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.webkit.JavascriptInterface;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;import java.io.IOException;...SuppressLint(StaticFieldLeak)private static Context mContext;SuppressLint(SetJavaScriptEnabled)Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mContext getApplicationContext();WebView mWebView findViewById(R.id.webview);mWebView.getSettings().setJavaScriptEnabled(true);mWebView.addJavascriptInterface(new JavaScriptBridge(), Android); // Export class JavaScriptBridge to WebView and map it to window.Android object in JavaScriptmWebView.setWebViewClient(new WebViewClient() {Overridepublic boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {if (request.getUrl().toString().equalsIgnoreCase(https://www.google.cn/)) {view.loadUrl(https://www.google.com/ncr);return true;} else if (request.getUrl().toString().startsWith(meowcat://open_settings)) {final Intent intent mContext.getPackageManager().getLaunchIntentForPackage(com.android.settings);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);mContext.startActivity(intent);return true;}return false;}Overridepublic void onPageFinished(WebView view, String url) {view.loadUrl(javascript:(() {const script document.createElement(script); script.src/MeowCat-Android-Asset/www/js/vconsole.min.js; document.body.append(script); script.onload () {alert(vConsole:Loaded!); if (typeof VConsole ! undefined) {new VConsole({onReady: () {const vc document.getElementById(__vconsole); const vc_switch vc.querySelector(.vc-switch); vc.style.position relative; vc.style.zIndex 9999999999; vc_switch.style.opacity opacity in this ? this.opacity : .5;},});}};})(););super.onPageFinished(view, url);}Overridepublic WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest webResourceRequest) {String url webResourceRequest.getUrl().toString();Uri uri Uri.parse(url);String key uri.getScheme() :// uri.getHost() /MeowCat-Android-Asset/;if (url.contains(key)) {String assetsPath url.replace(key, );try {return new WebResourceResponse(text/plain, UTF-8, getAssets().open(assetsPath));} catch (IOException e) {e.printStackTrace();}}return super.shouldInterceptRequest(view, webResourceRequest);}});mWebView.setWebChromeClient(new WebChromeClient() {Overridepublic boolean onJsAlert(WebView view, String url, String message, final JsResult result) {onJsDialog(DialogType.ALERT, view, url, message, result, null, null);return true;}Overridepublic boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {onJsDialog(DialogType.CONFIRM, view, url, message, result, null, null);return true;}Overridepublic boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) {onJsDialog(DialogType.PROMPT, view, url, message, null, defaultValue, result);return true;}});mWebView.loadUrl(file:///android_asset/www/index.html); // You can directly use file://android_asset/ to load the files in the assets folder}private enum DialogType {ALERT,CONFIRM,PROMPT}private static void onJsDialog(DialogType type, WebView view, String url, String message, final JsResult result, String defaultValue, final JsPromptResult promptResult) {AlertDialog.Builder builder new AlertDialog.Builder(view.getContext());String[] content message.split(:, 2);builder.setTitle(content[0]);builder.setMessage(content[1] \n url);builder.setCancelable(false);switch (type) {case PROMPT:builder.setPositiveButton(android.R.string.ok, (dialog, which) - promptResult.confirm(defaultValue)); // TODO: Inputbreak;case CONFIRM:builder.setCancelable(true);builder.setNegativeButton(android.R.string.cancel, (dialog, which) - result.cancel());case ALERT:default:builder.setPositiveButton(android.R.string.ok, (dialog, which) - result.confirm());}builder.create().show();}SuppressWarnings(unused)private static class JavaScriptBridge {JavascriptInterfacepublic void makeToast(final String message) {Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();}}...WebPage
...
script typetext/javascriptuse strict;alert(Alert Title:This is an alert);confirm(Confirm Title:This is a confirm) ? alert(Alert Title (Confirm):You confirmed the dialog) : alert(Alert Title (Confirm):You canceled the dialog);alert(Alert Title (Prompt):Prompt content is prompt(Prompt Title:This is a prompt, Hello world));window.Android.makeToast(Hello world);window.location https://www.google.cn/;
/script
...HTML
运行代码最终您将能够看到如下提示
vConsole
Loaded!
https://www.google.com/[OK]然后在页面的右下角会出现一个绿色按钮上面写着 vConsole。我们做到了那正是我们想要的。
常见问题
1. 前端如何调试WebView
首先要在WebView页面打开可以debug的设置。不过只支持KITKAT以上版本
scss 代码解读复制代码if(Build.VERSION.SDK_INT Build.VERSION_CODES.KITKAT) {mWeb.setWebContentsDebuggingEnabled(true);
}Android端需要开启开发者模式 然后打开usb调试 最后插上电脑。在Chrome地址栏输入Chrome://inspect。你会看到如下界面。 正常的话在App中打开WebView时chrome中会监听到并显示页面。
点击页面下的inspect就可以实时看到手机上WebView页面的显示状态了。 2.JS 如何传递 Uint8Array到 Android端
方法1: 注入参数为String data 的方法。通过Base64作为传输载体 前端将Uint8Array数据转Base64 Native侧将Base64解析为byte[]。方法2: 注入参数为byte[] bytes 的方法。 直接传递字符串 无论字符串多长传递时间都在 10ms内 推断字符串传递可能采用内存映射 直接传递内存地址. 传递uint8array 数据越长时间越长 推断可能底层涉及某些转换操作 从 js uint8 到 java byte。 3.Android端 如何加载本地前端资源
资源文件放置Assert文件夹中
标签加载
ini 代码解读复制代码script typemodule crossorigin src/android_asset/parkingtest/dist/assets/index.34d4f8c4.js/
link relstylesheet href/android_asset/parkingtest/dist/assets/index.cf521aaf.css代码加载URL
arduino代码解读
复制代码file:///android_asset/xxx/xxx/src.js资源文件放在本地SD存储
通过请求拦截方式 拦截前端资源请求 获取需要加载的文件名称通过JAVA IO 加载 File 返回给前端。
加载代码(伪代码)
scala 代码解读复制代码 public class MyWebViewClient extends WebViewClient {NullableOverridepublic WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {String url request.getUrl().toString();String fileName Fileurl.getFileName();ByteArrayInputStream fileStream JavaIO.loadFile(filePath fileName);return new WebResourceResponse(mimeType, encoding,statusCode, reasonPhrase, responseHeaders, byteArrayInputStream);}}引申阅读在 Android 开发者文档 中还有更多关于 Android WebView 混合开发的内容。 *1: NCR: No Country RedirectGoogle 支持禁用地区跳转功能。
参考Android WebView H5 Hybrid开发知识点整理 DSBridge for Android Java V8 通讯 深入理解JSCore