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. dnSpy PE format ( Portable Executable File Format)

    Portable Executable File Format PE Format  微软官方的 What is a .PE file in the .NET framework? [closed] ...

  2. How to change the button text of <input type=“file” />?

    How to change the button text of <input type=“file” />? Simply <label class="btn btn-p ...

  3. 装机、做系统必备:秒懂MBR和GPT分区表____转载网络

    装机.做系统必备:秒懂MBR和GPT分区表 科技美学 2016-10-17 16:36:23 阅读(3835) 评论(4) 很多网友询问MBR和GPT的问题,涉及到硬盘操作系统的安装,其实除了MBR和 ...

  4. LC 894. All Possible Full Binary Trees

    A full binary tree is a binary tree where each node has exactly 0 or 2 children. Return a list of al ...

  5. java tfserving grpc 通信调用代码解析 【重点参考】

    https://blog.csdn.net/shin627077/article/details/78592729/   [重点参考]

  6. ConstraintLayout的简单介绍和使用

    ConstraintLayout是Android Studio 2.2中主要的新增功能之一,也是Google在去年的I/O大会上重点宣传的一个功能.我们都知道,在传统的Android开发当中,界面基本 ...

  7. ControlTemplate in WPF —— DataGrid

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x ...

  8. 八十九:redis之python操作redis

    安装:pip install redis 连接 字符串操作 插入值 获取 删除值 列表操作,更多操作见源码 添加 获取 集合操作,更多操作见源码 哈希操作,更多操作见源码 事务操作:cache.pip ...

  9. LoadRunner 技巧之协议分析

    LoadRunner 技巧之协议分析 在做性能测试的时候,协议分析是困扰初学者的难题,选择错误的协议会导致Virtual User Generator 录制不到脚本:或录制的脚本不完整,有些应用可能需 ...

  10. YII :将oracle中timestamp 字段正常显示在页面中

    'value'=>'DateTime::createFromFormat("d#M#y H#i#s*A", $data["START_TIME"])-&g ...