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. @configuration和@component之间的区别

    @configuration和@component之间的区别是:@Component注解的范围最广,所有类都可以注解,但是@Configuration注解一般注解在这样的类上:这个类里面有@Value ...

  2. echarts ajax请求demo

    <body> <!--为ECharts准备一个具备大小(宽高)的Dom--> <div id="main" style="width: 10 ...

  3. compare across commits online

    https://gist.github.com/nevik/5689882 Examples: https://github.com/octocat/Spoon-Knife/compare/ed122 ...

  4. 内置对象(Date String Math Array)

    什么是对象 JavaScript 中的所有事物都是对象,如:字符串.数值.数组.函数等,每个对象带有属性和方法. 对象的属性:反映该对象某些特定的性质的,如:字符串的长度.图像的长宽等: 对象的方法: ...

  5. MySQL——逻辑分层与存储引擎

    MySQL是最受欢迎的开源SQL数据库管理系统,由Oracle Corporation开发,分发和支持. MySQL网站(http://www.mysql.com/)提供有关MySQL软件的最新信息. ...

  6. mariadb面试

    [mariadb主从架构的工作原理] 主节点写入数据以后,保存到二进制文件中,从节点生成IO线程和sql线程,IO线程请求读取二进制文件:主节点生成的dump线程,将数据发送到中继日志中,sql线程读 ...

  7. 微服务简介和SOA比较

    https://blog.csdn.net/chszs/article/details/78515231https://blog.csdn.net/wuxiaobingandbob/article/d ...

  8. xaml中显示 “大括号左边” 文本

    Content="{}{" 最合适的还是上面的写法 转义符{不好使的 要么 空格{ 要么 全角{ 要么binding

  9. 问题 1014: [编程入门]阶乘求和python):(本地测试正确;但提交不对!!??)求教

    问题 1014: [编程入门]阶乘求和 时间限制: 1Sec 内存限制: 128MB 提交: 27629 解决: 5450 题目描述 求Sn=1!+2!+3!+4!+5!+…+n!之值,其中n是一个数 ...

  10. 【HANA系列】SAP HANA SQL从给定日期中获取年份

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL从给定日 ...