相关工具
- http://debugtbs.qq.com (腾讯 x5内核调试地址)
- chrome://inspect (Chrome 调试地址,可调试远程 WebView)
- scrcpy (基于 adb,可在桌面上显示、操作手机)
问题描述
在上传图片的页面,页面第一次加载完后可以正常打开选择图片, 选完之后再点击上传就没反应了,或者取消选择后也不能再次选择 (后面试了下 IOS 系统,没有这种问题)
这是一个基于 uni-app 开发的 Web 项目, 安卓 APP 使用了腾讯的 x5 内核来代替原生的 WebView
排查思路
核对从 Web 到安卓的交互过程,先查看 Web 页面上传的逻辑
chooseTheImg() {
uni.chooseImage({
count: 1, //图片可选择数量
sizeType: ['original', 'compressed'], //original 原图,compressed 压缩图,默认二者都有
sourceType: ['album'], //album 从相册选图,camera 使用相机,默认二者都有。
success: res => {
let imgFiles = res.tempFilePaths //图片的本地文件路径列表
this.uploadTheImg(imgFiles)
this.$forceUpdate()
}
})
}
这里使用了 uni.chooseImage
,似乎没什么问题,再到 uni-app 源码中搜索 chooseImage,看一下它的实现
export function chooseImage ({
count,
// sizeType,
sourceType
}, callbackId) {
// TODO handle sizeType 尝试通过 canvas 压缩
if (imageInput) {
document.body.removeChild(imageInput)
imageInput = null
}
imageInput = _createInput({
count: count,
sourceType: sourceType
})
document.body.appendChild(imageInput)
// ignore...
imageInput.click()
}
可以看到,它是在 body 内追加 input 框来实现的文件选择,触发方式是调用 api 时,也同步调用一次 input 的 click 方法,这个可以到 chrome://inspect 页面中操作观察一下
按描述中的步骤操作,很容易复现这个问题,即使由我们自己手动再调用 click 方法,甚至再手动添加个 input 框来测试,也一样有问题。到此,确定应该是安卓端的问题,接下来就是排查一下安卓的逻辑
// For Android > 5.0
@Override
public boolean onShowFileChooser(com.tencent.smtt.sdk.WebView webView,
com.tencent.smtt.sdk.ValueCallback<Uri[]> uploadMsg, FileChooserParams fileChooserParams) {
//...
if (needCallback && uploadMsg != null) {
uploadMsg.onReceiveValue(null);
}
return true;
}
打一个 debug 包,断点调试,可以看到,点击上传后, 首次能进到这个方法,但后续都进不来, 结合这些关键信息,和 x5 手册里的指导,搜索一些资料做下参考
WebView调H5上传文件点击取消时无法再次响应H5上的选择文件事件
最后确认,这个问题也是上面的 ValueCallback
没有手动回调的原因,加上之后问题解决
附记
几天之后,测试人员又提了这个bug,说是在弹出授权的场景下,还会复现。 鉴于之前看过这里面的逻辑,知道其中判断条件多,比较复杂,所以猜测很可能是在授权条件里,没有手动做此回调,经过修改,和安卓人员确认之后,便简单修复了这个场景的问题。
另外,x5 内核的调试,需要先下载内核,并打开相应开关