精华内容
下载资源
问答
  • WebView与JS交互
    千次阅读
    2020-07-12 18:22:23

    阅读:JSBridge

    前言:以下是webView和JS互相调用的基础介绍。

    利用WebView调用网页上的JavaScript代码(java调用JS)

    说白了,只有一步,就是loadUrl,在WebView中调用Js的基本格式为:

    webView.loadUrl("javascript:methodName(parameterValues)"); 
    

    代码示例,现有以下这段JavaScript代码,将展示3种用法:

    <script type="text/javascript">
          function readyToGo() {
              alert("Hello")
          }
          function alertMessage(message) {
          alert(message)
      }
    
      function getYourCar(){
          return "Car";
      }
      </script>
    

    注意:需要在主线程中发起调用

    1. WebView调用JavaScript无参无返回值函数
     String call = "javascript:readyToGo()";
      webView.loadUrl(call);
    
    1. WebView调用JavScript有参无返回值函数
      String call = "javascript:alertMessage(\"" + "content" + "\")";
      webView.loadUrl(call);
    
    1. WebView调用JavaScript有参数有返回值的函数
    @TargetApi(Build.VERSION_CODES.KITKAT)
      private void evaluateJavaScript(WebView webView){
          webView.evaluateJavascript("getYourCar()", new ValueCallback<String>() {
              @Override
              public void onReceiveValue(String s) {
                  Log.d("findCar",s);
              }
          });
      }
    

    JavaScript通过WebView调用Java代码(JS调用java)

    从API19开始,Android提供了@JavascriptInterface对象注解的方式来建立起Javascript对象和Android原生对象的绑定,提供给JavScript调用的函数必须带有@JavascriptInterface。
    实际上,就是3个步骤:
    1,@JavascriptInterface注解;
    2,注册JavaScriptInterface;
    3,调用,如window.android.show("JavaScript called~!");

    演示一 JavaScript调用Android Toast方法
    1. 编写Java原生方法并用使用@JavascriptInterface注解
     @JavascriptInterface
      public void show(String s){
          Toast.makeText(getApplication(), s, Toast.LENGTH_SHORT).show();
      }
    

    2.注册JavaScriptInterface

     webView.addJavascriptInterface(this, "android");
    

    addJavascriptInterface的作用是把this所代表的类映射为JavaScript中的android对象。
    3.编写JavaScript代码

     function toastClick(){
          window.android.show("JavaScript called~!");
      }
    
    演示二 JavaScript调用有返回值的Java方法

    1.定义一个带返回值的Java方法,并使用@JavaInterface:

    @JavaInterface
      public String getMessage(){
          return "Hello,boy~";
      }
    

    2.添加JavaScript的映射

    webView.addJavaScriptInterface(this,"Android");
    

    3.通过JavaScript调用Java方法

      function showHello(){
          var str=window.Android.getMessage();
          console.log(str);
      }
    
    更多相关内容
  • WebView与Js交互

    2018-04-10 14:59:54
    Android 与Js交互的简单实现Demo 你们可以看看,必有收获
  • android不使用webview与js交互
  • Android中webview与JS交互、互调方法实例详解 前言: 对于试水的功能,一般公司都会采用H5的方式来开发,可以用很少的资源很短的项目工期来完成。 但许多情况下,H5页面会需要一些原生持有的一些如用户信息之类的...
  • Android app 网页交互 WebView 与JS交互 demo把人脸检测中人眼坐标传递到网页上显示出来,第一个想到的事webview, 但书上支持说用GET POST,并不能实现这种效果,请教罗享同志后百度webview与JS交互就有了.
  • 随着混合开发模式比较流行,很多时候,我们需要在原生的基础上,使用 WebView 加载网页,这样控制更加方便。今天我们来看看,如何将 Java 对象 和 List 集合传值给 JS 调用。 如何将 Java 对象实例传值给 JS 其实将...
  • x5webviewjs交互的三方库
  • WebView与js交互总结

    2020-08-06 21:06:32
    Android webview与js 交换JSON对象数据 使用Kotlin:让Android与JS交互的详解 js中eval()的使用说明 简介 使用 WebView 加载网页,有时候需要进行js交互,相互传递数据和响应事件。 android 调用 js 代码: ...

    【参考:】

    1. Android webview与js 交换JSON对象数据
    2. 使用Kotlin:让Android与JS交互的详解
    3. js中eval()的使用说明

    简介

    使用 WebView 加载网页,有时候需要进行js交互,相互传递数据和响应事件。
    android 调用 js 代码:

    1. WebView#loadUrl("javascript:func('" + arg + "')")
    2. WebView#evaluateJavascript(String script, @Nullable ValueCallback<String> resultCallback)

    js 调用 android 代码:

    1. 通过 WebView#addJavascriptInterface(Object object, String name) 进行对象映射
    2. 通过 WebViewClient#shouldOverrideUrlLoading() 来拦截Url调用代码
    3. 通过 WebChromeClientonJsAlert()onJsConfirm()
      onJsPrompt() 拦截 js 中的对话框 alert() / confirm() / prompt()

    Android(Kotlin)调用 JS

    Android 通过 loadUrl 调用 js 代码

    基础设置

    var settings = webView.settings
     // 支持js交互
    settings.javaScriptEnabled = true
    // 允许js弹窗
    settings.javaScriptCanOpenWindowsAutomatically = true
    // 使用dom存储,如果加载的是本地 assets 的 HTML,最好设为 false,否则可能会出现第一次加载空白
    settings.domStorageEnabled = true
    settings.cacheMode = WebSettings.LOAD_NO_CACHE
    settings.allowFileAccess = true
    settings.useWideViewPort = true
    settings.setSupportZoom(false) // 支持缩放
    
    settings.defaultTextEncodingName = "utf-8"
    settings.loadWithOverviewMode = true
    settings.setNeedInitialFocus(false)
    settings.userAgentString = settings.userAgentString + "; Android"
    
    /*解决图片不显示*/
    settings.blockNetworkImage = false //解决图片不显示
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        //允许混合(http,https)
        settings.mixedContentMode = WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE
    }
    

    Android 调用 js 方法

    // 不带参数
    webView.loadUrl("javascript:postShareParams()")
    
    // 带参数,常用参数 字符串(String),JSONArray 字符串(.toString()),JSONObject字符串(.toString())
    var data:JSONArray = ...
    // 要把字符串里的单引号转义一下(如果没转义的话)
    var json: String = data.toString().replace("'", "\\\'")
    // 防止这里成对的单引号,导致报错
    webView.loadUrl("javascript:setTreeData('${json}')")
    
    // 也可以是一段 js 代码,下面的代码即是暂停页面中的视频播放
    webView.loadUrl("javascript:(function() { var videos = document.getElementsByTagName('video'); for(var i=0;i<videos.length;i++){videos[i].pause();}})()")
    // 改变 span 的文字
    weView.loadUrl("javascript:$('#broadcast').find('span').text('暂停')")
    // 隐藏视图
    webView.loadUrl("javascript:$('#info_delete').hide()")
    

    如果调用 js 方法有传参,参数是一个 JSON 字符串( JSONArray 字符串(.toString())或 JSONObject字符串(.toString())),js 端需要使用 eval('(' + result + ')') 或者 "JSON.parse(result)" 将这个JSON 字符串解析为对象。

    function setTreeData(result) {
      alert(result);
      var data = eval('(' + result + ')');
      //var data = JSON.parse(result);
      //alert(JSON.stringify(data));
    
      // reloadChart(data)
    }
    

    使用 eval() 解析 json,容错能力较好,这种情况 [{}, {}, ] 依然能正常解析,而 JSON.parse() 则报错。
    eval 的用法可参考:js中eval()的使用说明:https://www.cnblogs.com/firstlady/p/11347382.html

    注意,android端不能直接传对象(会被转成地址,或对象重写的toString())给 js,但是可以通过上述方法将 JSON 字符串转成对象;android 端也不能直接接收对象,但是js可以通过JSON.stringify(data) 将对象转成一个 JSON 字符串再传给 android。

    Android 通过 evaluateJavascript() 调用JS代码

    先来说说使用这个方法的优点:

    使用这个方法不会刷新页面,如果使用第一种方法则会刷新页面
    *注意:这个方法只能在Android4.4之后使用

    使用方式:
    1 .将minSdkVersion最低版本改为19 (build.gradle----minSdkVersion)
    2. 直接替 loadUrl 方式

    androidWeb.evaluateJavascript("javascript:clickJS()",object : ValueCallback<String>{
                        override fun onReceiveValue(value: String?) {
    //                            这里返回JS的结果
                        }
                    })
    

    两种方式的区别:

    • loadUrl()

      • 使用起来方便简洁。
      • 但是他是在没有返回的情况下使用。
      • 效率比较低,获取返回值的时候很麻烦。
      • 并且调用的时候会刷新WebView
    • evaluateJavascript()

      • 效率比loadUrl ()高很多
      • 虽然效率高但是只支持Android4.4以上
      • 在获取返回值时候很方便
      • 调用时候不刷新WebView

    根据情况使用两种方式,我们可以根据当前项目开发的需求选择相应的使用方式,我们可以直接判断版本号来区分使用方式:

    if (Build.VERSION.SDK_INT< 18) {
        android_web.loadUrl("javascript:clickJS()")
    } else {
        android_web.evaluateJavascript("javascript:clickJS()"), {
            //返回JS方法中的返回值,我们没有写返回值所以为null
        }
    }
    

    参考:使用Kotlin:让Android与JS交互的详解

    js 调用 Android(Kotlin)

    使用WebView的addJavascriptInterface()进行对象映射

    webView.addJavascriptInterface(AndroidApi(), "AndroidApi")
    
    inner class AndroidApi {
    	
    	// 有返回值
    	@JavascriptInterface
    	fun getAppParams(): String {
    		var params = JSONObject()
    		
    		Utils.Clipboard.copy(mParams.token)
    		return params.toString()
    	}
    	
    	// 带参数
    	@JavascriptInterface
    	fun jumpDetail(data: String?) {
    		// { code: code, url: data, abstract: abstract }
    		var dataStr = StringUtils.getNonNullStr(data, "{}")
    		var type = object : TypeToken<LinkedHashMap<String, String>>() {}.type
    		var dataMap = Gson().fromJson<LinkedHashMap<String, String?>>(dataStr, type)
    		// ...
    	}
    }
    

    注意:android 端也不能直接接收对象,但是js可以通过JSON.stringify(data) 将对象转成一个 JSON 字符串再传给 android。

    使用 WebViewClient()shouldOverrideUrlLoading() 方法拦截Url调用 Android 代码

    <script type="text/javascript">
        function clickAndroid(){
            //定义url协议
            document.location = "js://webview?name=zhangsan&age=20&sex=0"
        }   
    </script>
    
    webView.webViewClient = object : WebViewClient() {
        override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
            super.onPageStarted(view, url, favicon)
        }
        
        override fun onPageFinished(view: WebView?, url: String?) {
            super.onPageFinished(view, url)
        }
        
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
            val url = request?.url.toString()
            
            return shouldOverrideUrlLoading(view, url)
        }
    
        override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
            //      获取Uri  这里的URL是我们在JS方法中写的URL协议"js://webview?name=zhangsan&age=20&sex=0"
          	val uri = Uri.parse(url)
         	if (uri.scheme == "js") {
            	if (uri.authority == "webview") {
              		val makeText = Toast.makeText(this@MainActivity, url, Toast.LENGTH_LONG)
              		makeText.setGravity(Gravity.CENTER, 0, 0)
              		makeText.show()
            	}
            	return true
          	} 
          	view?.loadUrl(url)
            return true
        }
    
        override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler, error: SslError) {
            handler.proceed() //接受所有网站的证书
        }
    }
    

    使用 WebChromeClientonJsAlert()onJsConfirm()onJsPrompt() 拦截JS中的对话框alert() / confirm() / prompt()

    js 代码,注意代码里的 alert(result)

    function setTreeData(result) {
      alert(result);
      var data = eval('(' + result + ')');
      //var data = JSON.parse(result);
      //alert(JSON.stringify(data));
    
      // reloadChart(data)
    }
    

    Kotlin 代码:

    webView.webChromeClient = object : WebChromeClient() {
    
        override fun onProgressChanged(view: WebView, newProgress: Int) {
    		// 进度变化回调,可用于设置进度条进度
        }
    
        override fun onReceivedTitle(view: WebView, title: String) {}
    
        override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
            Utils.Log.i("onJsAlert url=$url; message=$message")
            Toast.makeText(this@EventAnalysisActivity, message, Toast.LENGTH_LONG).show()
            result!!.confirm()
            return super.onJsAlert(view, url, message, result)
        }
        
        override fun onJsConfirm(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
    	    return super.onJsConfirm(view, url, message, result)
        }
    
        override fun onJsPrompt(view: WebView?, url: String?, message: String?, defaultValue: String?, result: JsPromptResult?): Boolean {
    	   return super.onJsPrompt(view, url, message, defaultValue, result)
       	}
    
    }
    

    这种方式页可以用作 js 的 debug 调试。

    三种方式的区别

    1. addJavascriptInterface() 使用起来方便简洁,但是在 Android 低版本下有问题,用于Android4.4以上。

    2. shouldOverrideUrlLoading() 使用起来没有漏洞,但是两端定协议,使用起来比较麻烦,主要用于不需要返回值的情况。

    3. onJsAlert()onJsConfirm()onJsPrompt() 拦截 js 中的对话框 alert() / confirm() / prompt() 和第二种方式一样,没有漏洞,而且也复杂,并且需要协议来规定它。

    展开全文
  • Android Webview 与JS交互

    2021-06-04 05:37:00
    Android中 WebView控件支持JS与本地代码的交互。// 是否允许在webview中执行javascriptwebSettings.setJavaScriptEnabled(true);//添加JS的接口名称mWebView.addJavascriptInterface(this, "mobiletojs");其主要分为...

    Android中 WebView控件支持JS与本地代码的交互。

    // 是否允许在webview中执行javascript

    webSettings.setJavaScriptEnabled(true);

    //添加JS的接口名称

    mWebView.addJavascriptInterface(this, "mobiletojs");

    其主要分为两类:

    1:JS调用本地代码

    通过window.mobiletojs.saveLogin(username, password);

    mobiletojs 对应 mWebView.addJavascriptInterface(this, "mobiletojs"); 中的接口名称

    2:本地代码调用JS

    在Activity中实现方法调用 mWebView.loadUrl("javascript:setUsername('ddd')");   即可实现对JS:设置用户名方法的调用

    //Android 本地代码

    package com.whroid.commonapp.ui;

    import android.annotation.SuppressLint;

    import android.app.Activity;

    import android.os.Bundle;

    import android.util.Log;

    import android.webkit.WebSettings;

    import android.webkit.WebView;

    @SuppressLint("JavascriptInterface")

    public class WebViewJSUI extends Activity {

    public static final String TAG = "WebViewJSUI";

    private WebView mWebView;

    @Override

    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    mWebView = new WebView(this);

    setContentView(mWebView);

    WebSettings webSettings = mWebView.getSettings();

    // 是否允许在webview中执行javascript

    webSettings.setJavaScriptEnabled(true);

    // 为JS添加本地调用的接口 名称

    mWebView.addJavascriptInterface(this, "mobiletojs");

    // 加载网页

    mWebView.loadUrl("file:///android_asset/test_webview_js.html");

    }

    //页面点击登录时 由页面调用

    public void saveLogin(String username,String password)

    {

    Log.w(TAG, "调用登录:onLoin:"+username+" password:"+password);

    }

    //由代码调用页面js,实现对页面的编辑

    public void setUsername()

    {

    mWebView.loadUrl("javascript:setUsername('ddd')");

    }

    public String getUsername()

    {

    return "来自android 的用户名";

    }

    public String getPassword()

    {

    return "mobile password";

    }

    }

    //对应的页面,以及相应的JS

    content="HTML Tidy for HTML5 (experimental) for Windows https://github.com/w3c/tidy-html5/tree/c63cc39" />

    title

    function onLogin() {

    var username = document.getElementById("username").value;

    var password = document.getElementById("password").value;

    var userAgent = navigator.userAgent;

    var index = userAgent.indexOf("Android");

    if (index > 0) {

    window.mobiletojs.saveLogin(username, password);

    }

    }

    function setUsername(name) {

    document.getElementById("username").value = name;

    }

    function onInit() {

    var userAgent = navigator.userAgent;

    var index = userAgent.indexOf("Android");

    if (index > 0) {

    //调用android或者ios本地方法,获取用户名或密码

    var username = window.mobiletojs.getUsername();

    var password = window.mobiletojs.getPassword();

    document.getElementById("username").value = username;

    document.getElementById("password").value = password;

    }

    }

    //页面开始加载时,触发

    if (document.readyState == "complete") {

    onInit()

    } else {

    document.onreadystatechange = function() {

    if (document.readyState == "complete") {

    onInit()

    }

    }

    }

    test

    οnclick="onLogin()" />

    &lbrack;android&rsqb; WebView与Js交互

    获取WebView对象 调用WebView对象的getSettings()方法,获取WebSettings对象 调用WebSettings对象的setJavaScriptEnabled()方法,设置j ...

    webview与js交互(转)

    原文:http://www.cnblogs.com/vanezkw/archive/2012/07/02/2572799.html 对于android初学者应该都了解webView这个组件.之前我也是 ...

    Android中使用WebView与JS交互全解析

    1.概述首先,需要提出一个概念,那就是hybrid,主要意思就是native原生Android和h5混合开发.为什么要这样做呢?大家可以想象一下针对于同一个活动,如果使用纯native的开发方式,An ...

    webview与js交互

     对于android初学者应该都了解webView这个组件.之前我也是对其进行了一些简单的了解,但是在一个项目中不得不用webview的时候,发现了webview的强大之处,今天就分享一下使用we ...

    android Webview 实现js调用java代码实现Activity跳转

    今天有了一个需求,在android里webview加载的html页面,要求点击html页面的按钮实现Activity的跳转. 咱是是菜鸟,webview的接触不多,于是就和度娘来了次亲密接触.在其中也 ...

    webView和js交互

    与 js 交互 OC 调用 JS // 执行 js - (void)webViewDidFinishLoad:(UIWebView *)webView { NSString *title = [web ...

    iOS webView与js交互在文本空格上输入文字

    项目要求:webview加载html网址,内容为填空题型文本,需要在横线上添加答案,并点击提交按钮后再将答案进行回显 正常加载的效果图片: 这个是用js交互后的效果图: 点击空格,输入想输入的答案,如 ...

    Android原生webview中js交互

    http://www.cnblogs.com/android-blogs/p/4891264.html Html页面和Java代码结合的方式一般用在界面经常被更改 的情况下,可以讲html放在网络中, ...

    Android WebView与JavaScript交互操作(Demo)

    应用场景: 为了使Android移动项目能够在较短的时间内完成开发,同时降低技术人员开发的成本投入,往往会采用Hybrid APP的开发模式.相关Hybrid APP(混合型应用)参看:http:// ...

    随机推荐

    关于js touch事件 的引用设置

    一开始做前端页面的时候,接触的也是js,但是随后便被简单高效的jquery吸引过去,并一直使用至今. 而js,则被我主观的认为底层技术而抛弃. 直到这几天工作需要,研究移动端页面的触屏滑动事件,搜索j ...

    (BFS)poj1465-Multiple

    题目地址 题意可理解为我们有一些给定的元素,要用它们组成数,如果一个长度(x)所有组成的数都不是给定的另一个数(n)的倍数,并且长度为x的数中有模n的不同于长度小于x的数模n的数,那么继续延长这个数的 ...

    Java基础-JVM类加载机制

    JVM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述: 1)Bootstrap ClassLoader /启动类加载器 $JAVA_HOME中jre/li ...

    wince下的CPU和内存占用率计算

    #include DWORD Caculation_CPU(LPVOID lpVoid) { MEMORYSTATUS MemoryInfo; DWORD Perc ...

    分享一款页面视差滚动切换jquery&period;localscroll插件

    今天给大家分享一款页面视差滚动切换jquery.localscroll插件. 滚动鼠标液动条看下页面的切换效果.该插件适用浏览器:IE8.360.FireFox.Chrome.Safari.Opera ...

    02线性表链式存储&lowbar;LinkList--&lpar;线性表&rpar;

    #include "stdio.h" #include "string.h" #include "ctype.h" #include &qu ...

    代码-Weka的LinearRegression类

    package kit.weka; import weka.classifiers.Evaluation; import weka.classifiers.functions.LinearRegres ...

    【排障】每次打开word都提示要安装配置

    为什么每次打开word都提示要安装配置?很多人在打开word时,总是提示要安装配置一遍,花去不少时间,这是由于电脑里有两个不同版本的office软件,产生的原因可能是原来的卸载了没卸载干净,或是安装了 ...

    数据结构算法及应用&mdash&semi;&mdash&semi;二叉树

    一.二叉树性质 特性1 包含n (n> 0 )个元素的二叉树边数为n-1 特性2 二叉树的高度(height)或深度(depth)是指该二叉树的层数(有几层元素,而不是有层的元素间隔) 特性3 ...

    展开全文
  • Android webview与js交互

    千次阅读 2020-10-28 13:28:52
    示例演示:点击Android按钮,即调用WebView JS(文本名为javascript)中callJS() 示例说明:为了方便展示,本文是采用Andorid调用本地JS代码说明;实际情况时,Android更多的是调用远程JS代码,即将加载的JS代码...

    Android 默认方法

    最全面总结 Android WebView与 JS 的交互方式

    Android调用JS代码

    对于Android调用JS代码的方法有2种:

    1. 通过WebView的loadUrl()
    2. 通过WebView的evaluateJavascript()

    示例演示:点击Android按钮,即调用WebView JS(文本名为javascript)中callJS()
    示例说明:为了方便展示,本文是采用Andorid调用本地JS代码说明;实际情况时,Android更多的是调用远程JS代码,即将加载的JS代码路径改成url即可
    在这里插入图片描述

    方式一:通过WebView的loadUrl()
    1、新建 javascript.html 放着 src/main/assets 文件夹下(选中 main,右键 new - folder - Assets Folder)

    <!DOCTYPE html>
    <html lang="en">
     <head>
      <meta charset="UTF-8">
      <meta name="Generator" content="EditPlus®">
      <meta name="Author" content="">
      <meta name="Keywords" content="">
      <meta name="Description" content="">
      <title>Document</title>
     </head>
     <body>
    	<script>
    	// Android需要调用的方法
    	function callJS(){
    	   alert("Android调用了JS的callJS方法");
    	}
    	</script>
     </body>
    </html>
    

    2、在Android里通过WebView设置调用JS代码

    public class MainActivity extends AppCompatActivity {
        WebView mWebView;
        Button button;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mWebView = (WebView) findViewById(R.id.webview);
    
            WebSettings webSettings = mWebView.getSettings();
    
            // 设置与Js交互的权限
            webSettings.setJavaScriptEnabled(true);
            // 设置允许JS弹窗
            webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
    
            // 先载入JS代码
            // 格式规定为:file:///android_asset/文件名.html
            mWebView.loadUrl("file:///android_asset/javascript.html");
    
            button = (Button) findViewById(R.id.button);
            button.setOnClickListener(v -> {
                // 通过Handler发送消息
                mWebView.post(new Runnable() {
                    @Override
                    public void run() {
                        // 注意调用的JS方法名要对应上
                        // 调用javascript的callJS()方法
                        mWebView.loadUrl("javascript:callJS()");
                    }
                });
    
            });
    
            // 由于设置了弹窗检验调用结果,所以需要支持js对话框
            // webview只是载体,内容的渲染需要使用webviewChromClient类去实现
            // 通过设置WebChromeClient对象处理JavaScript的对话框
            //设置响应js 的Alert()函数
            mWebView.setWebChromeClient(new WebChromeClient() {
                @Override
                public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
                    AlertDialog.Builder b = new AlertDialog.Builder(MainActivity.this);
                    b.setTitle("Alert");
                    b.setMessage(message);
                    b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            result.confirm();
                        }
                    });
                    b.setCancelable(false);
                    b.create().show();
                    return true;
                }
            });
        }
    }
    

    注意:JS代码调用一定要在 onPageFinished() 回调之后才能调用,否则不会调用
    onPageFinished()属于WebViewClient类的方法,主要在页面加载结束时调用

    方式二:通过WebView的evaluateJavascript()
    该方法的执行不会使页面刷新,而第一种方法(loadUrl )的执行则会。比第一种方法效率更高、使用更简洁。Android 4.4 后才可使用

    button.setOnClickListener(v -> {
                // 通过Handler发送消息
                mWebView.post(new Runnable() {
                    @Override
                    public void run() {
                        mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
                            @Override
                            public void onReceiveValue(String value) {
                                //此处为 js 返回的结果
                            }
                        });
                    }
                });
            });
    

    JS去调用Android的代码

    对于JS调用Android代码的方法有3种:

    1. 通过 WebView 的addJavascriptInterface()进行对象映射
    2. 通过 WebViewClient 的shouldOverrideUrlLoading()方法回调拦截 url
    3. 通过 WebChromeClient 的 onJsAlert()onJsConfirm()onJsPrompt()方法回调拦截JS对话框alert()confirm()prompt() 消息

    演示效果:
    在这里插入图片描述

    方式1:通过 WebView的 addJavascriptInterface() 进行对象映射
    1、定义一个与JS对象映射关系的Android类:AndroidtoJs

    public class AndroidtoJs extends Object {
        // 定义JS需要调用的方法
        // 被JS调用的方法必须加入@JavascriptInterface注解
        @JavascriptInterface
        public void hello(String msg) {
            System.out.println("JS调用了Android的hello方法");
        }
    }
    

    2、将JS代码以 .html 格式放到 src/main/assets 文件夹里

    <!DOCTYPE html>
    <html lang="en">
     <head>
      <meta charset="UTF-8">
      <meta name="Generator" content="EditPlus®">
      <meta name="Author" content="">
      <meta name="Keywords" content="">
      <meta name="Description" content="">
      <title>Document</title>
      <script>
    	function callAndroid(){
    		// 由于对象映射,所以调用test对象等于调用Android映射的对象
            test.hello("js调用了android中的hello方法");
        }
     </script>
     </head>
     <body>
    	//点击按钮则调用callAndroid函数
        <button type="button" id="button1" onclick="callAndroid()"></button>
     </body>
    </html>
    

    3、在Android里通过WebView设置Android类与JS代码的映射

    // 通过addJavascriptInterface()将Java对象映射到JS对象
            //参数1:Javascript对象名
            //参数2:Java对象名
            mWebView.addJavascriptInterface(new AndroidtoJs(), "test");//AndroidtoJS类对象映射到js的test对象
    

    此方法存在严重的漏洞问题,具体请看文章:你不知道的 Android WebView 使用漏洞

    方式2:通过 WebViewClient 的方法shouldOverrideUrlLoading ()回调拦截 url
    Android通过 WebViewClient 的回调方法shouldOverrideUrlLoading()拦截 url,解析该 url 的协议,如果检测到是预先约定好的协议,就调用相应方法
    1、将JS代码以 .html 格式放到 src/main/assets 文件夹里

    <!DOCTYPE html>
    <html lang="en">
     <head>
      <meta charset="UTF-8">
      <meta name="Generator" content="EditPlus®">
      <meta name="Author" content="">
      <meta name="Keywords" content="">
      <meta name="Description" content="">
      <title>Document</title>
      <script>
    	function callAndroid2(){
           /*约定的url协议为:js://webview?arg1=111&arg2=222*/
           document.location = "js://webview?arg1=111&arg2=222";
        }
    	</script>
     </head>
     <body>
        <button type="button" id="button" value="js调用安卓方式2" onclick="callAndroid2()"></button>
     </body>
    </html>
    

    2、在Android通过 WebViewClient复写shouldOverrideUrlLoading()

    mWebView.setWebViewClient(new WebViewClient() {
                                          @Override
                                          public boolean shouldOverrideUrlLoading(WebView view, String url) {
    
                                              // 步骤2:根据协议的参数,判断是否是所需要的url
                                              // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)
                                              //假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)
    
                                              Uri uri = Uri.parse(url);
                                              // 如果url的协议 = 预先约定的 js 协议
                                              // 就解析往下解析参数
                                              if (uri.getScheme().equals("js")) {
    
                                                  // 如果 authority  = 预先约定协议里的 webview,即代表都符合约定的协议
                                                  // 所以拦截url,下面JS开始调用Android需要的方法
                                                  if (uri.getAuthority().equals("webview")) {
    
                                                      //  步骤3:
                                                      // 执行JS所需要调用的逻辑
                                                      System.out.println("js调用了Android的方法");
                                                      // 可以在协议上带有参数并传递到Android上
                                                      HashMap<String, String> params = new HashMap<>();
                                                      Set<String> collection = uri.getQueryParameterNames();
                                                  }
                                                  return true;
                                              }
                                              return super.shouldOverrideUrlLoading(view, url);
                                          }
                                      }
            );
    

    该方式不存在方式1的漏洞,但JS获取Android方法的返回值复杂

    如果JS想要得到Android方法的返回值,只能通过 WebView 的 loadUrl ()去执行 JS 方法把返回值传递回去,相关的代码如下:

    // Android:MainActivity.java
    mWebView.loadUrl("javascript:returnResult("+3+")");
    
    // JS:javascript.html
    function returnResult(result){
        alert("result is" + result);
    }
    

    方式3:通过 WebChromeClient 的onJsAlert()onJsConfirm()onJsPrompt() 方法回调拦截JS对话框alert()confirm()prompt() 消息

    Android通过 WebChromeClient 的onJsAlert()onJsConfirm()onJsPrompt()方法回调分别拦截JS对话框
    (即上述三个方法),得到他们的消息内容,然后解析即可
    在这里插入图片描述
    下面的例子将用拦截 JS的输入框(即prompt()方法)。常用的拦截是:拦截 JS的输入框(即prompt()方法),因为只有prompt()可以返回任意类型的值,操作最全面方便、更加灵活;而alert()对话框没有返回值;confirm()对话框只能返回两种状态(确定 / 取消)两个值

    1、javascript 放在 assets 文件夹下

    <!DOCTYPE html>
    <html lang="en">
     <head>
      <meta charset="UTF-8">
      <meta name="Generator" content="EditPlus®">
      <meta name="Author" content="">
      <meta name="Keywords" content="">
      <meta name="Description" content="">
      <title>Document</title>
      <script>    
        function callAndroid3(){
         // 调用prompt()
         var result=prompt("js://webview?arg1=111&arg2=222");
         alert("demo " + result);
        }
    
    	</script>
     </head>
     <body>
        <button type="button" id="button3" onclick="callAndroid3()">js调用安卓方式3</button>
     </body>
    </html>
    

    当使用mWebView.loadUrl("file:///android_asset/javascript.html")加载了上述JS代码后,就会触发回调onJsPrompt(),具体如下:
    如果是拦截警告框(即alert()),则触发回调onJsAlert();
    如果是拦截确认框(即confirm()),则触发回调onJsConfirm();

    2、在Android通过WebChromeClient复写onJsPrompt()

    mWebView.setWebChromeClient(new WebChromeClient() {
          @Override
                public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                    // 根据协议的参数,判断是否是所需要的url(原理同方式2)
                    // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)
                    //假定传入进来的 url = "js://webview?arg1=111&arg2=222"(同时也是约定好的需要拦截的)
    
                    Uri uri = Uri.parse(message);
                    // 如果url的协议 = 预先约定的 js 协议
                    // 就解析往下解析参数
                    if ( uri.getScheme().equals("js")) {
    
                        // 如果 authority  = 预先约定协议里的 webview,即代表都符合约定的协议
                        // 所以拦截url,下面JS开始调用Android需要的方法
                        if (uri.getAuthority().equals("webview")) {
    
                            //
                            // 执行JS所需要调用的逻辑
                            System.out.println("js调用了Android的方法");
                            // 可以在协议上带有参数并传递到Android上
                            HashMap<String, String> params = new HashMap<>();
                            Set<String> collection = uri.getQueryParameterNames();
    
                            //参数result:代表消息框的返回值(输入值)
                            result.confirm("js调用了Android的方法成功啦");
                        }
                        return true;
                    }
                    return super.onJsPrompt(view, url, message, defaultValue, result);
                }
    
                /*// 通过alert()和confirm()拦截的原理相同,此处不作过多讲述
                // 拦截JS的警告框
                @Override
                public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                    return super.onJsAlert(view, url, message, result);
                }*/
    
                // 拦截JS的确认框
                @Override
                public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
                    return super.onJsConfirm(view, url, message, result);
                }
    
            });
    

    在这里插入图片描述

    使用 jsbridge

    Android与Js交互之JSBridge的使用
    Android 中BridgeWebView 简单使用,以及爬坑

    Android4.2以下的addJavascriptInterface存在安全漏洞,虽然在Android4.2之后用@JavascriptInterface代替了addJavascriptInterface但是由于兼容性和安全性问题,基本上我们不会再利用Android系统为我们提供的addJavascriptInterface方法或者@JavascriptInterface注解来实现,所以我们只能另辟蹊径,去寻找既安全,又能实现兼容Android各个版本的方案

    1、项目gradle文件中添加maven { url "https://jitpack.io" },位置如下

    allprojects {
        repositories {
            google()
            jcenter()
            maven { url "https://jitpack.io" }
        }
    }
    

    2、在module的gradle中添加依赖

    dependencies {
        ...
        implementation 'com.github.lzyzsd:jsbridge:1.0.4'
    }
    

    3、布局文件中用BridgeWebView代替WebView

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="10dp">
    
        <EditText
            android:id="@+id/et"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    
        <Button
            android:id="@+id/bt"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Android调用js方法" />
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:padding="10dp"
            android:text="以下是webview" />
    
        <com.github.lzyzsd.jsbridge.BridgeWebView
            android:id="@+id/webview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </LinearLayout>
    

    4、Activity 中的代码

    public class JsBridgeActivity extends AppCompatActivity {
        private EditText et;
        private Button bt;
        private BridgeWebView webview;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_jsbridge);
            et = (EditText) findViewById(R.id.et);
            bt = (Button) findViewById(R.id.bt);
            webview = (BridgeWebView) findViewById(R.id.webview);
            webview.setDefaultHandler(new DefaultHandler());
            webview.setWebChromeClient(new WebChromeClient());
            webview.loadUrl("file:///android_asset/test.html");
    //      注册监听方法当js中调用callHandler方法时会调用此方法(handlerName必须和js中相同)
            webview.registerHandler("submitFromWeb", new BridgeHandler() {
                @Override
                public void handler(String data, CallBackFunction function) {
                    Log.e("TAG", "js返回:" + data);
                    //显示js传递给Android的消息
                    Toast.makeText(JsBridgeActivity.this, "js返回:" + data, Toast.LENGTH_LONG).show();
                    //Android返回给JS的消息
                    function.onCallBack("我是js调用Android返回数据:" + et.getText().toString());
                }
            });
            bt.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    //              调用js中的方法(必须和js中的handlerName想同)
                    webview.callHandler("functionInJs", "Android调用js66", new CallBackFunction() {
                        @Override
                        public void onCallBack(String data) {
                            Log.e("TAG", "onCallBack:" + data);
                            Toast.makeText(JsBridgeActivity.this, data, Toast.LENGTH_LONG).show();
                        }
                    });
                }
            });
        }
    }
    

    5、html 放在 assets 文件夹中

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <!-- Compiled and minified CSS -->
        <link rel="stylesheet" href="./materialize.min.css">
        <!-- Compiled and minified JavaScript -->
        <script src="./materialize.min.js"></script>
        <title>Test</title>
    </head>
    <body>
    <div class="input-field col s6">
        <input placeholder="请输入数据" id="text1" type="text" class="validate">
    </div>
    <button class="waves-effect waves-light btn" onclick="testClick();">js调用Android方法</button>
    </body>
    <script>
             //js调用Android方法:接收Android传递过来的数据,并做处理
    
             function testClick() {
    
              //参数一:调用java中的方法   submitFromWeb是方法名,必须和Android中注册时候的方法名称保持一致
              //参数二:返回给Android端的数据,可以为字符串,json等信息
              //参数三:js接收到Android传递过来的数据之后的相应处理逻辑
    
                window.WebViewJavascriptBridge.callHandler(
                   'submitFromWeb'
                   , {'param': "JS成功接收到数据---"}
                   , function(responseData) {
                        alert(responseData)
                   }
               );
           }
    
           //JS注册事件监听
           function connectWebViewJavascriptBridge(callback) {
               if (window.WebViewJavascriptBridge) {
                   callback(WebViewJavascriptBridge)
               } else {
                   document.addEventListener(
                       'WebViewJavascriptBridgeReady'
                       , function() {
                           callback(WebViewJavascriptBridge)
                       },
                       false
                   );
               }
           }
    
            //注册回调函数,第一次连接时调用 初始化函数
           connectWebViewJavascriptBridge(function(bridge) {
                //初始化
               bridge.init(function(message, responseCallback) {
                   var data = {
                       'Javascript Responds': 'Wee!'
                   };
                   alert("jasdashjd");
                   responseCallback(data);
               });
    
    
               //Android调用js方法:functionInJs方法名称需要保持一致 ,并返回给Android通知
    
               bridge.registerHandler("functionInJs", function(data, responseCallback) {
                   alert(data);
                   var data2 = document.getElementById("text1").value;
                   var responseData = "我是Android调用js方法返回的数据---"+ data2;
                   responseCallback(responseData);
               });
           })
    </script>
    </html>
    
    

    运行效果:
    在这里插入图片描述

    WebView加载网页选择文件上传

    Android使用WebView加载网页选择文件上传
    在这里插入图片描述
    新建 upload.html 放在 assets 下

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,maximun-scale=1,mininum-scale=1,user-scale=1">
        <tile>文件选择</tile>
        <style>
            .filechooser {
                width: 95%;
                height: 50px;
                -webkit-background-clip: border-box;
            }
    
        </style>
        <script>
            var display = function(){
                var path = document.getElementById("file_chooser").textContent;
                document.getElementById("filechooser_display").innerHTML("<b>"+path+"</b>");
            }
    
        </script>
    </head>
    
    <body>
    <fieldset>
        <input class="filechooser" id="file_chooser" type="file" placeholder="选择文件" onchange="display()"
               oninput="display()">
        <p id="filechooser_display"></p>
    </fieldset>
    </body>
    
    </html>
    

    Activity

    public class UploadActivity extends AppCompatActivity {
        private WebView webView;
        private ValueCallback<Uri> uploadFile;
        private ValueCallback<Uri[]> uploadFiles;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_upload);
            webView = findViewById(R.id.webview);
            webView.setWebChromeClient(new WebChromeClient() {
                // For Android 3.0+
                public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
                    Log.i("test", "openFileChooser 1");
                    uploadFile = uploadFile;
                    openFileChooseProcess();
                }
    
                // For Android < 3.0
                public void openFileChooser(ValueCallback<Uri> uploadMsgs) {
                    Log.i("test", "openFileChooser 2");
                    uploadFile = uploadFile;
                    openFileChooseProcess();
                }
    
                // For Android  > 4.1.1
                public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                    Log.i("test", "openFileChooser 3");
                    uploadFile = uploadFile;
                    openFileChooseProcess();
                }
    
                // For Android  >= 5.0
                public boolean onShowFileChooser(WebView webView,
                                                 ValueCallback<Uri[]> filePathCallback,
                                                 WebChromeClient.FileChooserParams fileChooserParams) {
                    Log.i("test", "openFileChooser 4:" + filePathCallback.toString());
                    uploadFiles = filePathCallback;
                    openFileChooseProcess();
                    return true;
                }
            });
            webView.loadUrl("file:///android_asset/upload.html");
        }
    
        private void openFileChooseProcess() {
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            startActivityForResult(Intent.createChooser(i, "选择文件"), 0);
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                switch (requestCode) {
                    case 0:
                        if (uploadFile != null) {
                            Uri result = data == null || resultCode != RESULT_OK ? null
                                    : data.getData();
                            uploadFile.onReceiveValue(result);
                            uploadFile = null;
                        }
                        if (uploadFiles != null) {
                            Uri result = data == null || resultCode != RESULT_OK ? null
                                    : data.getData();
                            uploadFiles.onReceiveValue(new Uri[]{result});
                            uploadFiles = null;
                        }
                        break;
                    default:
                        break;
                }
            } else if (resultCode == RESULT_CANCELED) {
                if (uploadFile != null) {
                    uploadFile.onReceiveValue(null);
                    uploadFile = null;
                }
                if (uploadFiles != null) {
                    uploadFiles.onReceiveValue(null);
                    uploadFiles = null;
                }
            }
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            webView.onResume();
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            webView.onPause();
        }
    
        /**
         * 确保注销配置能够被释放
         */
        @Override
        protected void onDestroy() {
            if (webView != null) {
                webView.destroy();
            }
            super.onDestroy();
        }
    }
    

    对代码的一些解释:
    点击按钮需要模拟form提交的方式去上传文件, 此时会回调 openFileChooser(...)方法。 然后在这个方法里接收并处理参数ValueCallback <uri> uploadMsg 。里面的 uri就是所从本地选择的文件路径。然后通过 Intent 的startActivityForResult(…)方法跳转到系统选择文件的界面进行文件选择。 最后在onActivityResult(int requestCode, int resultCode, Intent data)方法中获取 data中的字符串路径,转换成Uri格式,并传给uploadMsg 即可

    上面就是4.4 以前的实现过程,5.0及以上的, webkit不再支持openFileChooser(...),而是使用onShowFileChooser(…)

    资源下载

    展开全文
  • 今天我将全面介绍Android通过WebView与JS交互的全面方式 阅读本文前请先阅读:Android开发:最全面、最易懂的Webview详解 #目录 1. 交互方式总结 Android与JS通过WebView互相调用方法,实际上是: Android...
  • iOS webview与js交互

    千次阅读 2019-05-08 11:27:57
    WebView是显示网页的主要控件,在实际工作共经常会用到,尤其是当需要用户有交互的时候,就会用到js,对于不太熟悉js的同事来说可能有点蒙,我们今天就来总结一下webview与js交互功能。 iOS12以后的版本不在支持...
  • X5Bridge X5Bridge Android本机和JavaScript之间的桥梁的库Google本机具有一组通信,实际上,它也可以完成回调交互i X5Bridge X5Bridge Android本机和JavaScript之间的桥梁的库一组通信,实际上,它也可以完成回调...
  • android中webview与js交互

    2017-03-08 11:08:04
    一个简单的android中webview与js交互的例子
  • WebView与JS交互方式 1 Android调用JS方法 Android调用JS代码的方式有2种: 通过WebView的loadUrl方法 通过WebView的evaluateJavascript方法 1.1 通过WebView的loadUrl方法 将需要调用的JS代码以.html格式放到src/...
  • 本篇文章主要介绍了Android WebView与JS交互全面详解(小结),实现了Android客户端Web网页交互,具有一定的参考价值,有兴趣的可以了解一下
  • 调用WebView对象的addJavascriptInterface(obj, interfaceName)方法,添加js接口,参数:Object对象,String接口名称(这个对象在js中的别名) 定义一个内部类MyJavascript 定义一个方法showToast
  • webview与js交互两种方式

    千次阅读 2019-01-08 10:46:22
    安卓里面经常会用到webview与js交互的问题,一般有两种方式处理。 1.通过web方面定义接口方式:(推荐) 安卓端代码实现: JavaScriptInterface JSInterface; wv = (WebView) findViewById(R.id.web); wv....
  • 前言: 最近公司的App为了加快...本篇主要介绍WebView与Javascript交互数据,关于如何将H5网页呈现在WebView上可以参考这篇博客文章:Android总结之WebView使用总结。 WebView与Javascript交互:  WebView与Javascr
  • 前言 现在很多App都选择混合开发模式,即App内置Web网页(Hybrid App),比如说很多电商...下面是对 Android通过WebView与JS交互 的总结 1. 交互方式总结 Android与JS通过WebView互相调用的方法,实际上是: A...
  • 当我们去开发一个基于web的android app时,我们第一需要处理的就是与JavaScript交互问题,Android需要做的事情就是开放某些特定的接口供web里的JavaScript调用,可以开放弹出框功能,Toast,界面跳转等等,这样...
  • 今天我将全面介绍Android通过WebView与JS交互的全面方式目录1. 交互方式总结Android与JS通过WebView互相调用方法,实际上是:Android去调用JS的代码 JS去调用Android的代码二者沟通的桥梁是WebView对于Android调用JS...
  • (2)Android中WebView与JS交互方式详解 (3)Android 中 WebView 使用漏洞相关介绍 (4)Android中WebView 缓存机制 &amp; 资源加载方案 目录 1. 交互方式总结 Android与JS通过WebView互相调用方法,...
  • android 原生webview与js交互 具体也可见个人简书(图文说明更加详细): 前言 Android与JS通过WebView互相调用方法,实际上是: 1、Android去调用JS的代码 2、JS去调用Android的代码 二者沟通的桥梁是WebView 对于...
  • 今天我将全面介绍Android通过WebView与JS交互的全面方式 目录 1. 交互方式总结 Android与JS通过WebView互相调用方法,实际上是: Android去调用JS的代码 JS去调用Android的代码 二者沟通的桥梁是WebVie
  • 前言 现在很多App里都内置了Web网页(Hybrid App),比如说很多电商平台,淘宝...今天我将全面介绍Android通过WebView与JS交互的全面方式 阅读本文前请先阅读:Android开发:最全面、最易懂的Webview详解 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,936
精华内容 9,574
关键字:

webview与js交互

友情链接: ANFSMC.zip