1. 交互方式总结

1Android与JS通过WebView互相调用方法,实际上是:

  • Android去调用JS的代码
  • JS去调用Android的代码
    二者沟通的桥梁是WebView

    对于Android调用JS代码的方法有2种: 
    1. 通过WebViewloadUrl() 
    2. 通过WebViewevaluateJavascript()

    对于JS调用Android代码的方法有3种: 
    1. 通过WebViewaddJavascriptInterface()进行对象映射 
    2. 通过 WebViewClient 的shouldOverrideUrlLoading ()方法回调拦截 url 
    3. 通过 WebChromeClient 的onJsAlert()onJsConfirm()onJsPrompt()方法回调拦截JS对话框alert()confirm()prompt() 消息

  • 2.1 Android通过WebView调用 JS 代码

  • mWebView =(WebView) findViewById(R.id.webview);
    mWebView.loadUrl("file:///android_asset/javascript.html");
    LocationActivity.this.webView.post(() -> LocationActivity.this.webView.evaluateJavascript(
    "javascript:locationDidChange('" + LocationActivity.this.locationString + "')", value -> {
    // 此处为 js 返回的结果
    }));

    2.2 JS通过WebView调用 Android 代码

  • 方式2:通过 WebViewClient 的方法shouldOverrideUrlLoading ()回调拦截 url

  • <!DOCTYPE html>
    <html> <head>
    <meta charset="utf-8">
    <title>Carson_Ho</title> <script>
    function callAndroid(){
    /*约定的url协议为:js://webview?arg1=111&arg2=222*/
    document.location = "js://webview?arg1=111&arg2=222";
    }
    </script>
    </head> <!-- 点击按钮则调用callAndroid()方法 -->
    <body>
    <button type="button" id="button1" onclick="callAndroid()">点击调用Android代码</button>
    </body>
    </html>
    private class MyWebViewClient extends WebViewClient {
    
            @TargetApi()
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    return this.shouldOverrideUrlLoading(view, request.getUrl().toString());
    } @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")) {
    Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + uri.getQueryParameter("tel")));
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    LocationActivity.this.startActivity(intent);
    } else if (uri.getAuthority().equals("location")) { LocationActivity.this.webView.post(() -> LocationActivity.this.webView.evaluateJavascript(
    "javascript:locationDidChange('" + LocationActivity.this.locationString + "')", value -> {
    // 此处为 js 返回的结果
    })); } else if (uri.getAuthority().equals("toast")) { Toast.makeText(LocationActivity.this, uri.getQueryParameter("info"), Toast.LENGTH_SHORT).show();
    } else if (uri.getAuthority().equals("takePhoto")) { photoIdent = uri.getQueryParameter("ident");
    openPopupWindow();
    } else if (uri.getAuthority().equals("takeVideo")) {
    /***************************** 录制视频 ***********************************/
    EventBus.getDefault().post(new VideoIdentEvent(uri.getQueryParameter("ident")));
    Intent intent = new Intent(LocationActivity.this, VideoActivity.class);
    intent.putExtra(VideoActivity.VIDEO_IDENT, uri.getQueryParameter("ident"));
    startActivity(intent);
    } else if (uri.getAuthority().equals("playVideo")) {
    /***************************** 播放视频 ***********************************/
    startActivity(new Intent(LocationActivity.this, VideoPlayerActivity.class).putExtra("path",
    uri.getQueryParameter("path")));
    } else if (uri.getAuthority().equals("takeAudio")) {
    /******************************** 录制音频 ********************************/
    dialogShow(uri.getQueryParameter("ident"));
    } else if (org.apache.commons.lang3.StringUtils.equals(uri.getAuthority(), "userLogin")) {
    /******************************** 登录 ********************************/
    String username = uri.getQueryParameter("username");
    if (TextUtils.isEmpty(username)) {
    return true;
    } JPushInterface.setAlias(LocationActivity.this, username.hashCode(), username); String account = uri.getQueryParameter("yx_username");
    String password = uri.getQueryParameter("yx_password"); chatFragment.startImLogin(username, account, password);
    } else if (org.apache.commons.lang3.StringUtils.equals(uri.getAuthority(), "userLogout")) {
    /******************************** 退出 ********************************/
    chatFragment.logout(); finish();
    } else if (org.apache.commons.lang3.StringUtils.equals(uri.getAuthority(), "playAudio")) {
    /***************************** 播放视频 ***********************************/
    MediaActivity.start(LocationActivity.this, uri.getQueryParameter("path"));
    } return true;
    } return false;
    }

    这种方式的优点就是不存在漏洞,并且稳定

原生+H5开发之:js交互【location方式】的更多相关文章

  1. 原生+H5开发之:Android webview配置

    在上一篇文章Android 原生开发.H5.React-Native开发特点,我们可以了解到三种Android开发方式的区别和优缺点.[Android开发:原生+H5]系列的文章,将主要讲解Andro ...

  2. Android 与H5之间的js交互

    之前项目做过一些Android和Html5之间js交互方面的东西,今天有时间就总结一下: 一.为什么要进行js交互: 为了方便原生开发和Html之间数据传递,在静态页面的情况下可以改变原生开发的页面: ...

  3. 鸿蒙系统应用开发之JS实现一个简单的List

    在之前的文章鸿蒙应用开发之怎么更好的远程连接手表模拟器做调试里我运行了一个穿戴设备的应用,利用JS UI实现了一个最简单的HelloWorld. 今天我打算在智慧屏设备上利用豆瓣音乐的接口数据实现一个 ...

  4. android webView开发之js调用java代码示例

    1.webView设置 webView.getSettings().setJavaScriptEnabled(true);//设置支持js webView.addJavascriptInterface ...

  5. H5开发之Eclipes 编码乱码问题

    1.编码不对 a.对某文件或某工程更改编码: 鼠标移到工程名或文件名,右键->Properties->Resource->Text file enCoding ->更改编码(G ...

  6. Android开发之UI的编程方式创建

    我们知道,android中一个activity对应一个xml的UI配置文件,除了用xml文件配置的方式创建用户界面外,还可以使用代码编程的方式来创建一个用户界面.如果用户界面需要在运行过程中动态生成的 ...

  7. (一〇七)iPad开发之modal的切换方式与展示方式

    在iPad上modal有四种切换方式,分别是竖直进入(由下到上,默认方式).水平翻转.淡入淡出. 属性要设置在将要modal出来的控制器上: /* typedef NS_ENUM(NSInteger, ...

  8. 微信小游戏开发之JS面向对象

    //游戏开发之面向对象 //在js的开发模式中有两种模式:函数式+面向对象 //1.es5 // 拓展一:函数的申明和表达式之间的区别 // 函数的申明: // function funA(){ // ...

  9. Android开发之5大布局方式详解

    Android中常用的5大布局方式有以下几种: 线性布局(LinearLayout):按照垂直或者水平方向布局的组件. 帧布局(FrameLayout):组件从屏幕左上方布局组件. 表格布局(Tabl ...

随机推荐

  1. 运维小知识之nginx---nginx配置Jboss集群负载均衡

      codyl 2016-01-26 00:53:00 浏览385 评论0 负载均衡 转自 运维小知识之nginx---nginx配置Jboss集群负载均衡-博客-云栖社区-阿里云https://yq ...

  2. js日期工具

    /** * 日期工具类 */ define(function(require, exports, module) { var constants = require("constants&q ...

  3. OAuth认证与授权

    什么是OAuth授权?   一.什么是OAuth协议 OAuth(开放授权)是一个开放标准. 允许第三方网站在用户授权的前提下访问在用户在服务商那里存储的各种信息. 而这种授权无需将用户提供用户名和密 ...

  4. MD5做为文件名。机器唯一码有电脑的CPU信息和MAC地址,这两个信息需要在linux或unix系统下才能获取吧。

    可以采用机器(电脑)唯一码 + 上传IP + 当前时间戳 + GUID ( + 随机数),然后MD5做为文件名.机器唯一码有电脑的CPU信息和MAC地址,这两个信息需要在linux或unix系统下才能 ...

  5. 详细介绍Linux finger命令的使用

    Linux 允许多个用户使用不同的终端同时登陆,Linux finger命令为系统管理员提供知道某个时候到底有多少用户在使用这台Linux主机的方法,对于这个简单的命令我们还是先介绍一下再举例吧. L ...

  6. java基础11 继承(super、extends关键字和重写,这三个要素出现的前提:必须存在继承关系)

    面向对象的三大特征: 1.封装   (将一类属性封装起来,并提供set()和get()方法给其他对象设置和获取值.或者是将一个运算方法封装起来,其他对象需要此种做运算时,给此对象调用) 2.继承   ...

  7. Floyd_Warshall(任意两点之间的最短路)

    /* O(V^3) 案例: 1 2 2 1 3 5 2 3 1 */ #include <cstdio>#include <iostream>using namespace s ...

  8. Delphi 通过字符串实例化类

    通过字符串创建窗体类对象 1.需要在程序初始化的时候将类注册,注册到对象 RegGroups:(TRegGroups)中,以便查找. 注册类使用的函数:RegisterClass ,窗体初始化操作放在 ...

  9. gym101431B

    以此纪念我都快忘了的后缀自动机(捂脸) 不过这题有两种做法: 用后缀自动机,先把原串再接遍中间加入特殊连接字符再把原串反接两遍,对这个新构造出的串做后缀自动机.(或者直接建立广义后缀自动机) 下面只要 ...

  10. c++ primer 4 数组和指针

    类比的思想学习数组和指针,c++提供类似于vector和迭代器的低级复合类型——数组和指针.与vector相似,数组可以保存某一种类型的一组对象:而他们的区别在于,数组的长度固定,数组一经创建就不允许 ...