1. 在Android客户端或Chrome浏览器弹出一个引导用户关注公众号的二维码

描述

客户端加载线上义诊Url,偶尔会弹出一个要求关注丁香园公众号的二维码

问题分析

后端会根据当前登录用户向前端界面注入一段如下js

<script>window.initialState = {currentLoginUser: {avatar: "https://askpub.dxycdn.com/avatar/128/default.png",simUid: "0",userId: "0",showApplyAnswererHint: false,isApplied: false,wxFollow: false}, environment: {server: 'prd'}}
</script>

界面上根据wxFollow字段以及白名单决定是否弹出公众号的二维码
当用户未登录却进入到了义诊界面,或者已登录但未关注公众号,同时,Url未在白名单内时,将引导用户关注公众号

解决方案

检查wxFollow字段是否为false,检查白名单内有无义诊的Url。
与产品讨论,最终确认将义诊Url加入到白名单,不再在此界面引导用户关注公众号。

2. Android客户端无法拦截Vue路由的问题

描述

客户端加载使用vue编写的单页面应用,vue进行路由时,没有回调WebView的shouldOverrideUrlLoading生命周期方法。onPageFinished生命周期方法被调用,但无法进行路由拦截。

问题分析

客户端加载使用vue编写的单页面应用,会将整个站点所有vue组件及较小的资源文件下载到本地,当用户点击医生条目将要跳转至医生详情页时,并不会产生网络资源的加载,也就不会回调客户端WebView类似shouldOverrideUrlLoading的生命周期方法。同时,从vue-router.js可知,createHref创建出类似[/#/demo]的锚点。vue路由时,根据ua进行区分,对于支持pushState的使用window.history.pushState(window.history.replaceState)方法修改Url,不触发hashchange,否则使用window.location.hash(window.location.replace)修改Url,触发hashchange。客户端不应仅根据hashchange来判断vue的路由变化。

示例:

window.history.pushState({ key: "475593.080" }, '', "http://localhost:8080/#/demo")
window.history.replaceState({ key: "123" }, '', "http://localhost:8080/#/")
window.location.hash="#/demo"
window.location.replace="#/demo"

解决方案

可以在入口js中(main.js),使用router.beforeEach注册一个全局前置钩子,同时,为确保客户端可以监控到所有vue路由信息,可以将钩子放置在router.start(new Vue())之前。当vue路由发生,全局前置钩子将按照创建顺序调用。钩子方法为异步解析执行,同时,路由将会等待所有钩子resolve完。需要确保所有钩子一定调用了next方法,否则钩子将不会被resolve,造成路由阻塞。
问题一:不调用next方法,将阻塞路由,造成history混乱。
问题二:to、from参数转化为json时要考虑循环引用问题,JSON.stringify()无法处理这些问题,可以引入三方库解决。
问题三:若vue路由时出现异常,整个跳转将出现混乱。当界面上其它地方出现异常,同时使用window.onerror(Vue.config.errorHandler或者try-catch)处理了异常,并进行了统一处理,应当小心添加统一处理异常的代码。

示例:

import Util from 'util'
router.beforeEach((to, from, next) => {if (window.AndroidJSBridger && window.AndroidJSBridger.beforeEach) {const toStr = to ? Util.inspect(to) : '{}';const fromStr = from ? Util.inspect(from) : '{}';//返回值boolean为true表示客户端已经拦截本次路由,将做进一步处理,返回false,表示客户端不关心本次路由。const ret = window.AndroidJSBridger.beforeEach(to.fullPath,toStr,fromStr)if(ret){next(false);}else{next(true);}} else {next(true);}
})

3. 前端接收到两个DXYJSBridgeReady事件的问题

描述

当h5界面运行在客户端时,h5界面监听了DXYJSBridgeReady事件,并收到多个DXYJSBridgeReady事件。

问题分析

当h5界面运行在客户端,需要调用客户端一些Api函数,客户端需要准备一些资源,并初始化这些Api函数。正是由于h5界面需要等待客户端初始化环境,固监听DXYJSBridgeReady事件,等客户端环境初始化。
客户端通过loadUrl(evaluateJavascript)向h5界面注入一段js,并通过window.document.dispatchEvent发送一个DXYJSBridgeReady事件,通知h5界面环境初始化完成。
当h5界面接收到多个DXYJSBridgeReady事件时,可能原因有如下几种,需逐一排查:
1)客户端反复注入同一JS片段,并且没有做防重复分发操作(解决-window.hasInitDXYJSBridgeReady标记位)
2)h5界面多处监听DXYJSBridgeReady事件或没做防重复监听操作(解决-全局搜索DXYJSBridgeReady,并删除)
3)h5界面主动分发了DXYJSBridgeReady事件(解决-全局搜索DXYJSBridgeReady,并删除)
3)h5界面监听DXYJSBridgeReady事件时,使用的立即执行函数(解决—查看监听器的写法,防止监听器立即执行)

解决方案

develop模式下,h5界面模拟原生客户端进行事件分发。界面上主动分发了DXYJSBridgeReady事件。故只需要删除模拟分发代码片段即可。

4. develop is not defined异常的问题

描述

查看义诊页,点击医生条目客户端控制台偶尔显示develop is not defined异常,此时整个界面无法响应事件。

问题分析

当点击医生条目时,触发了h5界面上的某些资源加载代码。此时WebView的生命周期方法onProgressChanged将被调用。客户端会将此情况理解为新界面的加载,并重新注入JS片段,为“新的”h5界面准备环境。
出现develop is not defined异常可能的原因有如下几种,需逐一排查:
1)客户端为“新的”h5界面准备环境时注入的JS片段中包含对未定义的develop变量的使用。(解决-查看所有客户端注入的js片段)
2)h5界面进行跳转时,调用中某些自定义函数或者三方库中包含对未定义的develop变量的使用。(解决-全局搜索整站所有前端代码)

解决方案

客户端为h5界面准备环境时,需利用window.env,告知h5界面客户端当前所处状态。由于客户端注入的js片段全部为字符串逐段拼接,导致调用了未定义的develop变量。只需要将develop变量转化为字符串即可解决。为规范化注入的JS,可以将待注入的js放入assets中,使用压缩-读取-替换的方式替代原有方案。压缩时,应当小心由单行注释或者末尾省略分号而带来的问题。

5. shouldOverrideUrlLoading用法过时问题

描述

WebView生命周期方法shouldOverrideUrlLoading使用了过旧的方式重写,可能导致整个WebView生命周期方法调用的改变。

问题分析

为支持2.X版本,以往WebView的shouldOverrideUrlLoading的用法为:

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {boolean isProcessed = processJumpUrl(url);if(!isProcessed) {if(mWebView != null) {mWebView.loadUrl(url);}return false;} else {return isProcessed;}
}

4.X以后
若没有设置WebViewClient则由系统(Activity Manager)处理该 url,通常是使用浏览器打开或弹出浏览器选择对话框。
若设置WebViewClient且该方法返回true ,则说明由应用的代码处理该url,WebView不处理,也就是程序员自己做处理。
若设置WebViewClient且该方法返回false,则说明由WebView处理该url,即用WebView加载该url。
用法如下:

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {boolean isProcessed = processJumpUrl(url);if (isProcessed){return true;}else {return super.shouldOverrideUrlLoading(view,url);}
}

解决方案

使用Google规定的方法重写WebView的shouldOverrideUrlLoading生命周期方法。

6. 解决义诊界面连续点击时与原生限流产生的冲突问题

描述

在客户端上,连续点击h5界面条目,客户端无法有效拦截所有h5的路由事件。产生的现象是,单击正常,而双击之后,h5跳转到了登录界面或者医生详情界面。

问题分析

客户端上,vue路由时,会询问客户端是否需要接管路由,若客户端表示不关心本次路由,h5界面将继续自身的路由操作。
对于h5界面发出的事件请求,客户端做了限流操作,减少用户因误操作,多次点击同一条目而产生的困扰。
单击时,客户端会接管路由,并正常进行处理。
双击时,客户端忽略了第二次路由,导致h5界面触发了原有路由规则。
此处,还有一点需要注意。限流操作时间阀值的计算应当小心修改,防止因频繁更新初始时间产生连续点击而不响应事件的效果。

解决方案

客户端做限流操作时,不能简单的直接忽略前端的路由请求,而应当将限流操作的意图通过某种方式,反馈到前端界面。可以通过假装已处理第二次路由的方式,让前端界面误认为本次路由已经被有效处理,而不再执行原有路由规则。

7. 关于义诊界面打开过慢的问题

描述

在客户端上,特别是网络较差的环境下,客户端打开义诊界面,加载速度非常缓慢。

问题分析

1)vue单界面应用,为提高用户进入站点后,进行站内跳转和操作的响应速度,使用了一次加载站点所有组件及较小的资源文件的方式。此方式以少量牺牲流量和界面初始化速度的方式换取了用户进入站点之后的操作响应速度。可考虑拆分的方式或者分平台自动打包的方式解决此问题。
2)vue应用可能包含一些不必要的三方库,影响界面加载速度。
3)客户端未正确设置缓存模式,导致界面二次加载过慢。
4)客户端安装包中可以提前包含部分三方库文件或者其它资源文件,待界面初次打开时,劫持并直接返回本地资源。
5)客户端针对部分或所有Url,与前端约定一套缓存规则,拦截Url-加载并缓存远程资源-二次打开返回本地数据。

Android-Hybrid-问题收集Android客户端无法拦截Vue路由的问题相关推荐

  1. Android 优秀文章收集整理集合

    转载 自    https://github.com/jiang111/awesome-android-tips 记录自己遇到的比较有价值的Android相关的blog MaHua是online md ...

  2. Android优秀文章收集(转载)

    http://blog.csdn.net/u010375364/article/details/52200425 http://blog.csdn.net/u010375364/article/det ...

  3. Android面试题收集

    Android是一种基于Linux的自由及开放源码的操作系统.主要使用于移动设备,如智能手机和平板电脑.由Google公司和开放手机联盟领导及开发.这里会不断收集和更新Android基础相关的面试题, ...

  4. Android 学习资料收集 1

    收集整理这份资料灵感来自于 trip_to_iOS, 征得同意引用了该资料的开头描述 收集整理这份资料主要帮助初学者学习 Android 开发, 希望能快速帮助到他们快速入门, 找到适合自己学习资料, ...

  5. Android日常开发收集的Tips

    Android日常开发收集的Tips 1. 时间戳转时间: 要注意时间戳的位数,10位的是秒级别的,13位的是毫秒级别的, 因此,在转化为时间中,也有稍微的区别. // 10位的秒级别的时间戳long ...

  6. Android学习资料收集

    博客 stormzhang 博主是上海薄荷科技开发主管, 他的博客分享了他从编程白痴到自学 Android 一路走过的经验, 写了一篇 Android学习之路 帮助了无数人, 里面还有很多好的文章非常 ...

  7. android开发我的新浪微博客户端-用户授权页面UI篇(3.1)

    看上面的图,其实这个页面的UI实现不复杂,首先是背景部分的实现这个参考 android开发我的新浪微博客户端-载入页面UI篇(1.1),重点来讲讲这个半透明的弹出对话框窗口是如何实现的,首先新建名为A ...

  8. android自定义尺子收集demo

    demo合集: https://github.com/dalong982242260/AndroidRuler 1.直尺(测量距离) github:https://github.com/1149863 ...

  9. 代码:android崩溃日志收集和处理

    用来处理android崩溃日志收集的代码,详情的使用请转:android崩溃日志收集和处理 第一个类 /** * 异常捕捉实现类 */ public class ErrorCaughtimplemen ...

最新文章

  1. String Reduction问题分析
  2. [物理学与PDEs]第2章第5节 一维流体力学方程组的 Lagrange 形式 5.1 引言
  3. TCP和UDP的区别(转)
  4. 【ABAP】SAP判断单据是否被锁定
  5. vue中img标签onerror事件
  6. 使用微软的 ilasm 和 ildasm 对. net程序进行编译和反编译
  7. mysql oracle 数据类型转换_Mysql与Oracle之间的数据类型转换
  8. PonyAI进军自动驾驶货运,乘用无人车历史性“小马过河”
  9. 密码学:身份认证详解
  10. unity3d 双人巡逻兵网络游戏
  11. 教学信息管理系统+SQL
  12. 仙人掌之歌——路转峰回(4)
  13. Mybatis复杂映射映射文件
  14. 诺贝尔物理学奖公布:LED灯将点亮了整个21世纪
  15. Excel提取单元格中的数字
  16. python快速爬虫视频_“python怎么快速爬虫视频“python 爬网页视频教程
  17. 考研复试—专业课英语
  18. 杭州云栖·2050大会-团聚召集人手册
  19. IC卡、ID卡、M1卡、射频卡的区别是什么【转】
  20. R语言实战应用精讲50篇(三十)-R语言ggplot2绘制精美高级地图

热门文章

  1. 第7章 集成方法、随机森林
  2. java gui 日历_Java实现简单日历小程序 Java图形界面小日历开发
  3. 基于51单片机的蓝牙计步器设计
  4. ftp下载命令行工具wget
  5. Python实现1~100猜数字小游戏
  6. 2021 美赛时间安排表
  7. 开源终端上网行为管理服务器windows版本包的编译及运行环境搭建
  8. python数据清洗面试题_利用python进行数据清洗
  9. 【c++篇】c++常见容器中list的模拟实现
  10. C++ Eigen 库中旋转向量、旋转矩阵、欧拉角、四元数的定义及互相转换