Android 原生webview传递header前端H5如何接收

Stella981
• 阅读 728

开发背景
跟其他公司合作的一个项目,传递参数的方式为原生通过自定义header头参数,由前端来接收。
踩坑
1 原生传参
安卓原生传参的方式很简单,通过webview.loadUrl这个方法,如下:

   Map<String, String> map = new HashMap<String, String>();
   map.put("Payment-Token", "*****");
   myWebView.loadUrl(myEdit.getText().toString(), map);

2 H5接收参数
也很简单,在网上查到的是ajax的方式,但是最后项目用的原生获取header参数的,没必要为了接收个参数,在我大VUE框架里引入jquery,如下:

 let req = new XMLHttpRequest();
      req.open('GET', document.location, false);
      req.send(null);
      let paymentToken = req.getResponseHeader('payment-token') ? req.getResponseHeader('payment-token') : '';
      this.paymentToken = paymentToken;
      if (paymentToken == '') {
        this.setShade('订单信息获取失败');
      }

你看,多么简单。然后测试的时候就被啪啪打脸了。前端说没收到参数,原生说传了,互相僵持了一下午,最后用修改UserAgent的方式来传递参数的

myWebView.getSettings().setUserAgentString("****");

今天开会,觉得这种方式不行不正规,还是要用之前loadUrl的方式传递header参数,忽然公司的大佬一句话点醒了我,纯前端VUE只能接收到response的header。

重点来了
请求一个网页其中包括了一次request(请求)以及一次response(响应)。所以,我们常说的header头也有两个,一个是request的header头,一个是response的header头。问题点就在这,圈起来。原生那边发的是request的header,而H5则接收的是response的header。
这个时候服务器的作用就来了,公司用的是nginx服务器,我在其中做了一些配置,逻辑就是获取request中的header参数,然后动态设置到response的header中,打完收工,代码如下

add_header 'Payment-Token' '$http_payment_token';

其中也可以看出,单纯前端VUE项目与渲染页面式前端项目(php,python)项目的区别,前者的权限没有后者的权限那么多,像php能直接通过Request->header的方式读取request的参数,而VUE则不行。


我们来看看以下几个webview使用的案列。

参考文献:

WebView详解与简单实现Android与H5互调

案例一header

直接上需求效果图:

Android 原生webview传递header前端H5如何接收

需求:WebView添加header,h5读取头部,并且隐藏底部菜单栏。

需要添加的header数据:ECR-APP:android

我们平时大多数情况使用的是loadUrl(String url)加载方法,下面我们来看另一个loadUrl构造方法。

loadUrl(String url, Map<String, String> additionalHttpHeaders)

参数additionalHttpHeaders字面上的意思是:额外的http头部信息。这个方法是Android 2.2 (也就是API 8),WebView新增加了一个接口方法,就是为了便于我们加载网页同时又可以发送HTTP头信息的。

看看具体的使用:

    HashMap<String, String> header = new HashMap<>();
    header.put("ECR-APP", "android");

    mWebView.loadUrl("http://m.test.366ec.net/Default2c.aspx",header);

马上运行效验一下:

Android 原生webview传递header前端H5如何接收

网页上底部的菜单已经去掉了。

案例二cookie

cookie用于记录用户登录信息,用户下次进入需要登录的界面不再需要重复登录。

先看看需求:

Android 原生webview传递header前端H5如何接收

会一直出现登录界面。那么怎么解决多次登录问题?WebView会将加载的url通过http请求传输到服务器。那么Cookie信息会通过header传递过去。

设置cookie代码如下:

    private void syncCookieToWebView(String url, List<String> cookies) {
        CookieSyncManager.createInstance(this);
        CookieManager cm = CookieManager.getInstance();
        cm.setAcceptCookie(true);
        if (cookies != null) {
            for (String cookie : cookies) {
                cm.setCookie(url, cookie);//注意端口号和域名,这种方式可以同步所有cookie,包括sessionid
            }
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
            CookieManager.getInstance().flush();
        } else {
            CookieSyncManager.getInstance().sync();
        }
    }

以下是调用代码:

   List<String> cookies = new ArrayList<>();
    //键值对类型  用等号("=")连接    具体根据后台给定
    cookies.add("StoreManagerTicket=" + "加密token");//根据后台协商而定
    syncCookieToWebView("加载的地址", cookies);

CookieManager会将这个Cookie存入该应用程序/data/data/databases/目录下的webviewCookiesChromium.db数据库的cookies表中。打开网页,WebView从数据库中读取该cookie值,放到http请求的头部,传递到服务器。

运行一下,看看还会出现多次登录的问题吗?

Android 原生webview传递header前端H5如何接收

跳转正常,没有出现多次登录的问题。

案例三注入js

不知道你在项目中遇到这样的场景没有?手机端与h5交互,提供数据支持。如调本地相机,获取到的图片上传到网页;调用定位返回地址给网页;调用二维码扫描界面返回扫描结果等等。

如下,有这样一个场景,网页上有【扫描】图标,点击打开手机扫描界面,扫描成功后上传扫描结果。那么在手机端一般会有如下方法:

JsOpenScanFunction(String callbackFunction)

参数callbackFunction表示扫描成功后webview.load调用的方法并且只有一个参数(扫描结果)。

一般前端h5会这样进行调用Android手机端打开二维码的方法:

//callback回调方法
window.JsInterface.JsOpenScanFunction(callback)

ios端会这样调用:

window.webkit.messageHandlers.JsOpenScanFunction.postMessage(callback)

在h5端会分步处理,无疑会增加开发人员的工作量,试想一下,如果交互的地方很多,那么h5端开发人员作何感想?而且后期的维护也是一件非常繁琐的事情,就没有更好的方案吗?

如果h5端可以像调用本地方法那样简单调用手机端方法,那不是非常fashion。

那么就需要分别在Android端和ios端分布注入js代码,方便h5端调用。

注入的方式如下:

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
        if (mIsAddJsCode) {//默认true
            mIsAddJsCode = false;
            mWebView.loadUrl("javascript:" + "function JsOpenScanFunction(s) {\n    window.JsInterface.JsOpenScanFunction(s);\n}");
        }
    }

在onPageStarted方法下注入js方法:

function JsOpenScanFunction(s) {
    window.JsInterface.JsOpenScanFunction(s);
}

这样h5只需要调用JsOpenScanFunction(s)方法就可以实现不同平台调用二维码扫描的功能。从此妈妈在已不担心多端调用的问题了。

注意:JsOpenScanFunction(s) 方法,需要前端和移动端事先约定。
参考:https://blog.csdn.net/u012551350/article/details/56674602

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这