如何建个人免费网站,手机怎么做网站免费的,济南专业的网站建设公司,上传设计作品集的网站目录二、具体分析2.1 Android通过WebView调用 JS 代码方式1#xff1a;通过WebView的loadUrl()方式2#xff1a;通过WebView的evaluateJavascript()方法对比使用建议2.2、JS通过WebView调用 Android 代码2.2.1、方法分析方式1#xff1a;通过 WebView的addJavascriptInterfa…
目录二、具体分析2.1 Android通过WebView调用 JS 代码方式1通过WebView的loadUrl()方式2通过WebView的evaluateJavascript()方法对比使用建议2.2、JS通过WebView调用 Android 代码2.2.1、方法分析方式1通过 WebView的addJavascriptInterface进行对象映射方式2通过 WebViewClient 的方法shouldOverrideUrlLoading ()回调拦截 url方式3通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息三种方式的对比 使用场景相关文章阅读
Android WebView使用攻略 Github下载地址Android WebView与JS互调 # 一、交互方式总结 Android与JS通过WebView互相调用方法实际上是 Android去调用JS的代码 JS去调用Android的代码 二者沟通的桥梁是WebView 对于Android调用JS代码的方法有2种 通过WebView的loadUrl() 通过WebView的evaluateJavascript()
对于JS调用Android代码的方法有3种 通过 WebView 的 addJavascriptInterface()进行对象映射 通过 WebViewClient 的 shouldOverrideUrlLoading() 方法回调拦截 url 通过 WebChromeClient 的 onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截 JS 对话框alert()、confirm()、prompt()消息
二、具体分析
2.1 Android通过WebView调用 JS 代码
对于Android调用JS代码的方法有2种 通过WebView的loadUrl() 通过WebView的evaluateJavascript()
方式1通过WebView的loadUrl() 实例介绍点击Android按钮即调用WebView JS文本名为javascript中callJS() 具体使用
步骤1将需要调用的JS代码以.html格式放到src/main/assets文件夹里 1、为了方便展示本文是采用Andorid调用本地JS代码说明 2、实际情况时Android更多的是调用远程JS代码即将加载的JS代码路径改成url即可 需要加载JS代码androidcalljs.html
!DOCTYPE html
htmlheadmeta charsetutf-8titleJava调用JS方法/title!-- JS代码 --script!-- Android需要调用的方法 --function callJS(){alert(Android调用了JS的callJS方法);}/script/head
/html步骤2在Android里通过WebView设置调用JS代码
Android代码AndroidCallJS1.java
package com.davis.webviewjs.demo;import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;public class AndroidCallJS1 extends AppCompatActivity {private Button btn;private WebView webview;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_webview);init();}private void init(){btn (Button)findViewById(R.id.btn);webview (WebView)findViewById(R.id.webview);WebSettings webSettings webview.getSettings();// 设置与Js交互的权限webSettings.setJavaScriptEnabled(true);// 设置允许JS弹窗webSettings.setJavaScriptCanOpenWindowsAutomatically(true);// 先载入JS代码// 格式规定为:file:///android_asset/文件名.htmlwebview.loadUrl(file:///android_asset/androidcalljs.html);btn.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {webview.post(new Runnable() {Overridepublic void run() {// 注意调用的JS方法名要对应上// 调用javascript的callJS()方法webview.loadUrl(javascript:callJS());}});}});// 由于设置了弹窗检验调用结果,所以需要支持js对话框// webview只是载体内容的渲染需要使用webviewChromClient类去实现// 通过设置WebChromeClient对象处理JavaScript的对话框//设置响应js 的Alert()函数webview.setWebChromeClient(new WebChromeClient() {Overridepublic boolean onJsAlert(WebView view, String url, String message, final JsResult result) {AlertDialog.Builder b new AlertDialog.Builder(AndroidCallJS1.this);b.setTitle(Alert);b.setMessage(message);b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {Overridepublic void onClick(DialogInterface dialog, int which) {result.confirm();}});b.setCancelable(false);b.create().show();return true;}});}
} 效果图特别注意JS代码调用一定要在 onPageFinished() 回调之后才能调用否则不会调用。 onPageFinished()属于WebViewClient类的方法主要在页面加载结束时调用 方式2通过WebView的evaluateJavascript()
优点该方法比第一种方法效率更高、使用更简洁。 1、因为该方法的执行不会使页面刷新而第一种方法loadUrl 的执行则会。 2、Android 4.4 后才可使用 具体使用
// 只需要将第一种方法的loadUrl()换成下面该方法即可
webview.evaluateJavascript(javascript:callJS(), new ValueCallbackString() {Overridepublic void onReceiveValue(String value) {//此处为 js 返回的结果Log.i(WEBVIEW_JS, value : value);}
});方法对比
调用方式优点缺点使用场景使用loadUrl()方便简洁效率低获取返回值麻烦不需要获取返回值对性能要求较低时使用evaluateJavascript()效率高向下兼容性差仅Android 4.4以上可用Android 4.4以上
使用建议
两种方法混合使用即Android 4.4以下使用方法1Android 4.4以上方法2
// Android版本变量
final int version Build.VERSION.SDK_INT;
// 因为该方法在 Android 4.4 版本才可使用所以使用时需进行版本判断
if (version 18) {webview.loadUrl(javascript:callJS());
} else {webview.evaluateJavascriptjavascript:callJS(), new ValueCallbackString() {Overridepublic void onReceiveValue(String value) {//此处为 js 返回的结果}});
}2.2、JS通过WebView调用 Android 代码
对于JS调用Android代码的方法有3种 通过 WebView 的 addJavascriptInterface() 进行对象映射 通过 WebViewClient 的 shouldOverrideUrlLoading() 方法回调拦截 url 通过 WebChromeClient 的 onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt()消息
2.2.1、方法分析
方式1通过 WebView的addJavascriptInterface进行对象映射
步骤1定义一个与JS对象映射关系的Android类AndroidtoJs
AndroidtoJs.java注释已经非常清楚
// 继承自Object类
public class AndroidtoJs extends Object {// 定义JS需要调用的方法// 被JS调用的方法必须加入JavascriptInterface注解JavascriptInterfacepublic void hello(String msg) {System.out.println(JS调用了Android的hello方法);}
}步骤2将需要调用的JS代码以.html格式放到src/main/assets文件夹里
需要加载JS代码jscallandroid.html
!DOCTYPE html
htmlheadmeta charsetutf-8titleJS调用Java方法/titlescriptfunction callAndroid(){!-- 由于对象映射所以调用test对象等于调用Android映射的对象 --test.hello(js调用了android中的hello方法);}/script/headbody!-- 点击按钮则调用callAndroid函数 --button typebutton idbutton1 onclickcallAndroid()/button/body
/html步骤3在Android里通过WebView设置Android类与JS代码的映射
package com.davis.webviewjs.demo;import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;public class JSCallAndroid1 extends AppCompatActivity {private Button btn;private WebView webview;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_webview);init();}private void init() {btn (Button)findViewById(R.id.btn);btn.setVisibility(View.GONE);webview (WebView)findViewById(R.id.webview);WebSettings webSettings webview.getSettings();// 设置与Js交互的权限webSettings.setJavaScriptEnabled(true);// 设置允许JS弹窗webSettings.setJavaScriptCanOpenWindowsAutomatically(true);// 通过addJavascriptInterface()将Java对象映射到JS对象//参数1Javascript对象名//参数2Java对象名webview.addJavascriptInterface(new AndroidtoJs(), test);//AndroidtoJS类对象映射到js的test对象// 先载入JS代码// 格式规定为:file:///android_asset/文件名.htmlwebview.loadUrl(file:///android_asset/jscallandroid.html);}
} 特点
优点使用简单 仅将Android对象和JS对象映射即可 缺点存在严重的漏洞问题
方式2通过 WebViewClient 的方法shouldOverrideUrlLoading ()回调拦截 url
具体原理 Android通过 WebViewClient 的回调方法shouldOverrideUrlLoading ()拦截 url 解析该 url 的协议 如果检测到是预先约定好的协议就调用相应方法 即JS需要调用Android的方法 具体使用
步骤1在JS约定所需要的Url协议
JS代码jscallandroid2.html 以.html格式放到src/main/assets文件夹里 !DOCTYPE html
htmlheadmeta charsetutf-8titleJava调用JS方法/title!-- JS代码 --scriptfunction callAndroid(){!-- 约定的url协议为js://webview?arg1111arg2222 --document.location js://webview?arg1111arg2222;}/script/headbody!-- 点击按钮则调用callAndroid函数 --button typebutton idbutton1 onclickcallAndroid()JS调用Android方法/button/body/html当该JS通过Android的webview.loadUrl(file:///android_asset/jscallandroid2.html)加载后就会回调shouldOverrideUrlLoading()接下来继续看步骤2
步骤2在Android通过WebViewClient复写shouldOverrideUrlLoading()
JSCallAndroid2.java
package com.davis.webviewjs.demo;import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;import java.util.HashMap;
import java.util.Set;public class JSCallAndroid2 extends AppCompatActivity {private Button btn;private WebView webview;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_webview);init();}private void init() {btn (Button)findViewById(R.id.btn);btn.setVisibility(View.GONE);webview (WebView)findViewById(R.id.webview);WebSettings webSettings webview.getSettings();// 设置与Js交互的权限webSettings.setJavaScriptEnabled(true);// 设置允许JS弹窗webSettings.setJavaScriptCanOpenWindowsAutomatically(true);// 先载入JS代码// 格式规定为:file:///android_asset/文件名.htmlwebview.loadUrl(file:///android_asset/jscallandroid2.html);webview.setWebViewClient(new WebViewClient(){Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {// 步骤2根据协议的参数判断是否是所需要的url// 一般根据scheme协议格式 authority协议名判断前两个参数//假定传入进来的 url js://webview?arg1111arg2222同时也是约定好的需要拦截的Uri uri Uri.parse(url);// 如果url的协议 预先约定的 js 协议// 就解析往下解析参数if ( uri.getScheme().equals(js)) {// 如果 authority 预先约定协议里的 webview即代表都符合约定的协议// 所以拦截url,下面JS开始调用Android需要的方法if (uri.getAuthority().equals(webview)) {// 步骤3// 执行JS所需要调用的逻辑Log.i(WEBVIEW_JS,js调用了Android的方法);// 可以在协议上带有参数并传递到Android上HashMapString, String params new HashMap();SetString collection uri.getQueryParameterNames();Log.i(WEBVIEW_JS, URI : uri);}return true;}return super.shouldOverrideUrlLoading(view, url);}});}
}
特点 优点不存在方式1的漏洞 缺点JS获取Android方法的返回值复杂。 如果JS想要得到Android方法的返回值只能通过 WebView 的 loadUrl 去执行 JS 方法把返回值传递回去相关的代码如下 // AndroidMainActivity.java
webview.loadUrl(javascript:returnResult( result ));// JSjavascript.html
function returnResult(result){alert(result is result);
}方式3通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息
在JS中有三个常用的对话框方法
方法作用返回值备注alert()弹出警告框没有在文本加入\n可换行confirm()弹出确认框两个返回值- 返回布尔值- 通过该值可判断点击时确认还是取消true表示确认false表示取消。prompt()弹出输入框任意设置返回值- 点击【确认】返回输入框的的值- 点击【取消】返回null。
方式3的原理Android通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt() 方法回调分别拦截JS对话框 即上述三个方法得到他们的消息内容然后解析即可。
下面的例子将用 拦截JS的输入框即prompt方法 说明 1、常用的拦截是拦截 JS的输入框即prompt方法 2、因为只有prompt可以返回任意类型的值操作最全面方便、更加灵活而alert对话框没有返回值confirm对话框只能返回两种状态确定 / 取消两个值 步骤1加载JS代码如下
jscallandroid3.html 以.html格式放到src/main/assets文件夹里 !DOCTYPE html
htmlheadmeta charsetutf-8titleJava调用JS方法/title!-- JS代码 --script!-- Android需要调用的方法 --function callJS(){var result prompt(js://webview?arg1111arg2222);alert(result : result);}/script/headbody!-- 点击按钮则调用callAndroid函数 --button typebutton idbutton1 onclickcallJS()JS调用Android方法/button/body/html当使用webview.loadUrl(file:///android_asset/jscallandroid3.html)加载了上述JS代码后就会触发回调onJsPrompt()具体如下 1、如果是拦截警告框即alert()则触发回调onJsAlert 2、如果是拦截确认框即confirm()则触发回调onJsConfirm 步骤2在Android通过WebChromeClient复写onJsPrompt()
package com.davis.webviewjs.demo;import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.LinearLayout;public class JSCallAndroid3 extends AppCompatActivity {private Button btn;private WebView webview;private LinearLayout layout;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_webview);init();}private void init() {btn (Button)findViewById(R.id.btn);btn.setVisibility(View.GONE);webview (WebView)findViewById(R.id.webview);WebSettings webSettings webview.getSettings();// 设置与Js交互的权限webSettings.setJavaScriptEnabled(true);// 设置允许JS弹窗webSettings.setJavaScriptCanOpenWindowsAutomatically(true);// 先载入JS代码// 格式规定为:file:///android_asset/文件名.htmlwebview.loadUrl(file:///android_asset/jscallandroid3.html);webview.setWebChromeClient(new WebChromeClient(){Overridepublic boolean onJsAlert(WebView view, String url, String message, JsResult result) {// 根据协议的参数判断是否是所需要的url(原理同方式2)// 一般根据scheme协议格式 authority协议名判断前两个参数//假定传入进来的 url js://webview?arg1111arg2222同时也是约定好的需要拦截的Log.i(WEBVIEW_JS, message : message);Uri uri Uri.parse(message);// 如果url的协议 预先约定的 js 协议// 就解析往下解析参数if ( uri.getScheme().equals(js)) {// 如果 authority 预先约定协议里的 webview即代表都符合约定的协议// 所以拦截url,下面JS开始调用Android需要的方法if (uri.getAuthority().equals(webview)) {//Log.i(WEBVIEW_JS, js调用了Android的方法);// 拦截alert()之后必须调用result.confirm()方法否则会出现白屏result.confirm();return true;}}return super.onJsAlert(view, url, message, result);}Overridepublic boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {// 根据协议的参数判断是否是所需要的url(原理同方式2)// 一般根据scheme协议格式 authority协议名判断前两个参数//假定传入进来的 url js://webview?arg1111arg2222同时也是约定好的需要拦截的Log.i(WEBVIEW_JS, message : message);Uri uri Uri.parse(message);// 如果url的协议 预先约定的 js 协议// 就解析往下解析参数if ( uri.getScheme().equals(js)) {// 如果 authority 预先约定协议里的 webview即代表都符合约定的协议// 所以拦截url,下面JS开始调用Android需要的方法if (uri.getAuthority().equals(webview)) {//Log.i(WEBVIEW_JS, js调用了Android的方法);// 拦截alert()之后必须调用result.confirm()方法否则会出现白屏result.confirm(js调用了Android的方法);return true;}}return super.onJsPrompt(view, url, message, defaultValue, result);}Overridepublic boolean onJsConfirm(WebView view, String url, String message, JsResult result) {return super.onJsConfirm(view, url, message, result);}});}Overrideprotected void onDestroy() {if (webview ! null) {webview.loadDataWithBaseURL(null, , text/html, utf-8, null);webview.clearHistory();((ViewGroup) webview.getParent()).removeView(webview);webview.destroy();webview null;}super.onDestroy();}
}三种方式的对比 使用场景
调用方式优点缺点使用场景通过addJavascriptInterface()进行添加对象映射方便简洁Android 4.2以下存在漏洞问题Android 4.2以上相对简单的互调场景通过WebVeiw的方法shouldOverrideUrlLoading()回调拦截url不存在漏洞问题- 使用复杂需要进行协议的约束- 从Native层往Web层传递值比较繁琐不需要返回值情况下的互调场景通过WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框消息不存在漏洞问题使用复杂需要进行协议的约束能满足大多数情况下的互调场景