微信内置浏览器 长按识别二维码 功能的两三个坑与解决方案
这篇文章是上一篇文章的延伸与总结,做的一个微信游戏宣传页上要调用长按识别二维码的功能,做的过程中遇到了两个坑,后来在组里分享会上分享了入坑经历,然后再度发现一个坑。本文就是在分享会上发言总结而成。
坑一:iOS 版微信长按识别二维码无法正常识别的bug
(8.21 更新:最新版6.2.4 已经修复该bug)
以下实测在iOS 版(iPhone)微信6.2.2 中有此bug,安卓版微信暂时没有发现有此bug。建议看下面的内容前先看这篇文章。
“众所周知”,在一些使用在微信内置浏览器的页面上要调用其长按识别二维码的功能,需要将二维码图片单独切出,img 标签形式展现。长按识别二维码 的原理Jeff 不甚了解,但却发现其有一个实际可识别区域上移的bug:对于二维码区域,实际可识别区域是整体上移64px,64px 的偏移量与二维码大小本身无关。
下面是一个重现bug 的Demo 页面,请用iPhone 版微信扫描:
红色的色块区域是我单独为了定位区域而写的,不是在二维码本身(具体可以查看上面Demo 的源代码),用手指长按你可以看到实际可识别二维码区域为红色部分:即整体可识别区域上移了64px,而往下拉看到不同大小的二维码你会发现这个64px 的偏移量与二维码本身大小无关。友情提示:你可以用小拇指在边界区域长按以确认。
为什么是神秘的64px 偏移量?答案是:64px 正好是微信内置浏览器标题栏+系统标题栏的高度。可以猜测的是,微信客户端在识别二维码的时候忽略了微信标题栏+系统状态栏的高度。
后来进一步排查的时候,发现二维码大到一定程度就没有“识别上移”的诡异现象了,大概是二维码大小在400px 以上的时候就没有(当然,这个是在iPad 版微信上测出来的),具体可以查看下面这个Demo 页面:
人在微信实习,所以后面经过与微信 iOS 开发人员的反馈沟通,确定是微信的 bug,也的确是这个64px 的问题;据他们的说法目前已经修复,但能否在下一个版本中加入么,就不得而知了。
解决方案的话有两个:
1)通过img增加padding 增大可接触面积;这个需要微调。
2)为二维码图片本身增加透明底部背景,这也是我们团队采用的方案。类似下图的样子,前端上用户是看不到的;但有个缺点就是如果用户保存二维码后则不是那么好看。
坑二:两(多)张两张二维码无法在同一屏幕视窗中共存
小标题说的“同一屏幕视窗”是指微信内置浏览器中在当前的手机屏幕上显示的可见范围,我们发现,当同一同一屏幕视窗中存在两个或以上的二维码的时候,微信客户端就会识别错误,无论你按哪个二维码长按识别,识别出来都是同一个目标。这个问题在iOS 版(iPhone)微信2.2及安卓版上均有之。
下面是一个演示Demo 页面,请用目标手机(iPhone 或安卓机上)微信扫描访问,然后长按识别二维码:
该页面一共有六个二维码,两两分组为三组,每组的二维码的信息分别是指向qq.com、baidu.com 的url。为了保证每次只有一组二维码在当前屏幕可视范围,页面特意将每组二维码距离拉得很大。每次请保持只有一组二维码在你当前屏幕范围内,然后请依次长按识别二维码。你会发现无论无论你按哪个二维码长按识别,识别出来都是同一个目标。
然后再尝试最后一组二维码,尝试通过滚动页面使得某个二维码不在你的屏幕可见范围,再执行长按识别二维码。
通过上面的Demo 页面,其实我们可以猜测微信中长按识别二维码的运行原理,就是你长按的时候相当于将当前手机屏幕截屏,识别截屏后的图片,这样一张图片有两个二维码图的时候当然只会识别出一个。顺着这个思路也可以解释上述坑一,因为截屏的图片当然包括了系统状态栏那部分,也就不难理解为什么会有“识别上移”的诡异现象了。
解决方案的话就是不要将两个二维码共存在同一个页面中。
坑三:多次执行长按二维码的功能会导致内存泄露,手机会变卡
这个是组里的同事在分享会那天做演示的时候发现出来的,多次执行长按二维码的功能会导致手机(iPhone)变卡。之前我做测试的时候也发现,多次测试后居然右键都识别出来是二维码图片(即没有出现“识别二维码”的按钮)。
写完本文,感谢一起探究的同事hz***h、do***e。
- 从源代码到Runtime发生的重排序编译器重排序指令重排序内存系统重排序阻止重排序
- 内存屏障保证缓存一致性优化
- 最新XSS 0day漏洞来袭,影响最新版本IE浏览器(含POC)
- Java内存模型—JMMhappens-before规则
- 那些年我们一起用过的Hybrid App
- 来看看美帝人民的安全意识:安全研究人员指责iOS版Outlook存在多处安全隐患
- 不是原配也可以-对接非原生配体
- oj放苹果
- 漏洞追踪:最新IE UXSS漏洞技术分析
- 如何使用Python超参数的网格搜索ARIMA模型
- int string相互转换
- Android 增量更新和升级
- web服务器集群集群是什么?分布式是什么?集中式是什么?例子缺点
- 图的遍历算法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Head First设计模式——生成器模式和责任链模式
- Head First设计模式——蝇量模式和解释器模式
- 【每日一题】33. Search in Rotated Sorted Array
- 【每日一题】34. Find First and Last Position of Element in Sorted Array
- 【每日一题】35. Search Insert Position
- Head First设计模式——原型模式和访问者模式
- Java 新特性前瞻:封印类
- 每天手撕一道算法题-130. 被围绕的区域
- C#实现前向最大匹、字典树(分词、检索)
- Tomcat 中文乱码,设置UTF-8
- 从零搭建Spring Boot脚手架(4):手写Mybatis通用Mapper
- IDEA将Maven项目中指定文件夹下的xml等文件编译进classes
- 数据误操作,教你使用ApexSQLLog工具从 SQLServer日志恢复数据!
- 从零搭建Spring Boot脚手架(5):整合 Mybatis Plus
- SQL Server数据库阻塞,死锁查询