Android原生与H5交互的实现

H5调用原生的方式

方式可能有多种,根据开发经验,接触过两种方式。

方法一:Android向H5注入全局js对象,也就是H5调Android

1.首先对WebView进行初始化

WebSettings settings = webview.getSettings();

settings.setJavaScriptEnabled(true); //允许在WebView中使用js

2.创建一个类JavaScriptMetod,专门用来给js提供可调用的方法

3.创建该类的构造方法,提供两个参数,WebView对象和上下文对象

private Context mContext;

private WebView mWebView;

public JavaScriptMethod(Context context, WebView webView) {

  mContext = context;

  mWebView = webView;

}

4.创建一个字符串常量,作为android与js通信的接口,即字符串映射对象

public static final String JAVAINTERFACE = "javaInterface";

5.接下来就是创建给js调用的方法,方法的参数接收一个json字符串(注意:在Android4.2之后,为了提高代码安全性,方法必须使用注解@JavascriptInterface,否则无法调用)

@JavascriptInterface

//andorid4.2(包括android4.2)以上,如果不写该注解,js无法调用android方法

public void showToast(String json){

  Toast.makeText(context, json, Toast.LENGTH_SHORT).show();

}

6.在WebView初始化代码中执行如下代码

//创建上面创建类的对象

JavaScriptMetod m = new JavaScriptMetod(this, webview);

//其实就是告诉js,我提供给哪个对象给你调用,这样js就可以调用对象里面的方法

//第二个参数就是该类中的字符串常量

webview.addJavascriptInterface(m, JavaScriptMetod.javaInterface);

现在,在js中就可以调用JavaScriptMetod中的方法了,调用方式如下

//参数一般为json格式

var json = {"name":"javascript"};

//javaInterface是上面所说的字符串映射对象

window.javaInterface.showToast(JSON.stringify(json));

网络上介绍js与android原生交互的文章里,大部分都是上面这种方式,但是这种方式并不适用于ios,也就是说,window.javaInterface.showToast(JSON.stringify(json))这样的js代码并不适用于ios,如果用以上的方法,就得分别为android和ios各

写一套js代码。这样很显然是不太合理的,所以在实际开发中,一般都使用接下来的第二种方法。

方法二:H5发起自定义协议请求,Android拦截请求,再由Android调用H5中的回调函数

这种方法实现的思想是js发出一个url请求,并将所需的参数添加到该url中。android端通过webView.setWebViewClient()拦截url,解析url中携带的参数,并根据参数信息进行相应的操作。

1.与方法一相同,首先都需要对webview进行初始化

WebSettings settings = webview.getSettings();

settings.setJavaScriptEnabled(true); //允许在WebView中使用js

2.首先看js中的代码是怎么写的

$("#showtoast").click(function () {

  var json = {"data": "I am a toast"};

  window.location.href="protocol://android?code=toast&data="+JSON.stringify(json);

});

$("#call").click(function () {

  var json = {"data": "10086"};

  window.location.href="protocol://android?code=call&data="+JSON.stringify(json);

});

这里定义两个点击事件,分别控制android显示toast和打电话的操作。其中,protocol://android为自定义的H5与android间的通信协议,与http请求进行区分。code规定了要进行的操作,data为传输的数据。

3.android中的代码

webView.setWebViewClient(new WebViewClient() {

  @Override

  public boolean shouldOverrideUrlLoading(WebView view, String url) {

  /**

  * 通过判断拦截到的url是否含有pre,来辨别是http请求还是调用android方法的请求

  */

  String pre = "protocol://android";

  if (!url.contains(pre)) {

    //该url是http请求,用webview加载url

    return false;

  }

  //该url是调用android方法的请求,通过解析url中的参数来执行相应方法

  Map map = getParamsMap(url, pre);

    String code = map.get("code");

    String data = map.get("data");

    parseCode(code, data);

    return true;

  }

});

其中,getParamsMap()方法从拦截到的url解析出code,data参数,parseCode()方法将根据不同的code进行相应的操作,代码如下:

private Map getParamsMap(String url, String pre) {

  ArrayMap queryStringMap = new ArrayMap<>();

    if (url.contains(pre)) {

      int index = url.indexOf(pre);

      int end = index + pre.length();

      String queryString = url.substring(end + 1);

      String[] queryStringSplit = queryString.split("&");

      String[] queryStringParam;

      for (String qs : queryStringSplit) {

        if (qs.toLowerCase().startsWith("data=")) {

          //单独处理data项,避免data内部的&被拆分

          int dataIndex = queryString.indexOf("data=");

          String dataValue = queryString.substring(dataIndex + 5);

          queryStringMap.put("data", dataValue);

        } else {

          queryStringParam = qs.split("=");

          String value = "";

            if (queryStringParam.length > 1) {

              //避免后台有时候不传值,如“key=”这种

              value = queryStringParam[1];

            }

          queryStringMap.put(queryStringParam[0].toLowerCase(), value);

        }

      }

    }

  return queryStringMap;

}

private void parseCode(String code, String data) {

  if(code.equals("call")) {

    try {

      JSONObject json = new JSONObject(data);

      String phone = json.optString("data");

      //执行打电话的操作,具体代码省略

      PhoneUtils.call(this, phone);

    } catch (JSONException e) {

      e.printStackTrace();

    }

  return;

}

if(code.equals("toast")) {

  try {

    JSONObject json = new JSONObject(data);

    String toast = json.optString("data");

    Toast.makeText(this, toast, Toast.LENGTH_SHORT).show();

  } catch (JSONException e) {

    e.printStackTrace();

  }

  return;

 }

}

最后,特别说明一下shouldOverrideUrlLoading()方法的返回值问题,该方法的返回值有三种:

  • 返回true,即根据代码逻辑执行相应操作,webview不加载该url;

  • 返回false,除执行相应代码外,webview加载该url;

  • 返回super.shouldOverrideUrlLoading(),点进父类中,我们可以看到,返回的还是false。

客户端相关知识学习(三)之Android原生与H5交互的实现的更多相关文章

  1. 客户端相关知识学习(十一)之Android H5交互Webview实现localStorage数据存储

    前言 最近有一个需求是和在app中前端本地存储相关的,所以恶补了一下相关知识 webView开启支持H5 LocalStorage存储 有些时候我们发现写的本地存储没有起作用,那是因为默认WebVie ...

  2. 客户端相关知识学习(十二)之iOS H5交互Webview实现localStorage数据存储

    前言 最近有一个需求是和在app中前端本地存储相关的,所以恶补了一下相关知识 webView开启支持H5 LocalStorage存储 有些时候我们发现写的本地存储没有起作用,那是因为默认WebVie ...

  3. 客户端相关知识学习(八)之Android“.9.png”

    参考 Android中.9图片的含义及制作教程 .9.png Android .9.png 的介绍

  4. 客户端相关知识学习(六)之deeplink技术

    Deeplink应用描述 Deeplink,简单讲,就是你在手机上点击一个链接之后,可以直接链接到app内部的某个页面,而不是app正常打开时显示的首页.不似web,一个链接就可以直接打开web的内页 ...

  5. 客户端相关知识学习(一)之混合开发,为什么要在App中使用H5页面以及应用场景、注意事项

    混合开发 随着移动互联网的高速发展,常规的开发速度已经渐渐不能满足市场需求.原生H5混合开发应运而生,目前,市场上许多主流应用都有用到混合开发,例如支付宝.美团等.下面,结合我本人的开发经验,简单谈一 ...

  6. 客户端相关知识学习(九)之h5给app传递数据

    方法一: 情况一: if (window.JdAndroid){          window.JdAndroid.setPayCompleted();          window.JdAndr ...

  7. 客户端相关知识学习(五)之什么是webView

    webview是什么?作用是什么?和浏览器有什么关系? Android系统中内置了一款高性能 webkit 内核浏览器,在 SDK 中封装为一个叫做 WebView 组件也就是说WebView是一个基 ...

  8. 客户端相关知识学习(四)之H5页面如何嵌套到APP中

    Android原生如何渲染H5页面 Android与 H5 的交互方式大概有以下 1 种: 利用WebView进行交互(系统API) iOS原生如何渲染H5页面 iOS 与 H5 的交互方式大概有以下 ...

  9. 客户端相关知识学习(二)之h5与原生app交互的原理

    前言 现在移动端 web 应用,很多时候都需要与原生 app 进行交互.沟通(运行在 webview中),比如微信的 jssdk,通过 window.wx 对象调用一些原生 app 的功能.所以,这次 ...

随机推荐

  1. Linux 多线程按照线程顺序打印字符

    #include <stdio.h> #include <pthread.h> #include <unistd.h> ; pthread_mutex_t mute ...

  2. oracle性能诊断sql

    --1.阻塞及等待事件信息查询-- 查询所有会话的状态.等待类型及当前正在执行的SQL脚本select t.SID, t.SERIAL#, t.Status, t.Action, t.Event, t ...

  3. koa 项目实战(五)全球公用头像的使用

    1.安装模块 npm install gravatar --save 2.使用 根目录/routes/api/users.js const gravatar = require('gravatar') ...

  4. Deep Visualization:可视化并理解CNN

    原文地址:https://zhuanlan.zhihu.com/p/24833574 一.前言 CNN作为一个著名的深度学习领域的“黑盒”模型,已经在计算机视觉的诸多领域取得了极大的成功,但是,至今没 ...

  5. javascript之注册事件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. 代码实现:定义一个文件输入流,调用read(byte[] b)方法,将a.txt文件中的内容打印出来(byte数组大小限制为5)

    package com.loaderman.test; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; im ...

  7. 手动部署 Ceph Mimic 三节点

    目录 文章目录 目录 前文列表 部署拓扑 存储设备拓扑 网络拓扑 基础系统环境 安装 ceph-deploy 半自动化部署工具 部署 MON 部署 Manager 部署 OSD 部署 MDS 部署 R ...

  8. openstack共享组件--rabbitmq消息队列(1)

    一.MQ 全称为 Message Queue, 消息队列( MQ ) 是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们. 消息传 ...

  9. 【转】Java IOUtils方式上传下载文件 on HDFS

    [From]https://www.cnblogs.com/areyouready/p/9795442.html package com.css.hdfs04; import java.io.File ...

  10. Window Relationships and Frames

    If a page contains frames, each frame has its own window object and is stored in the frames collecti ...