今天在APP架构师看到这个,因为以前做过有点模糊了,所以接他之手记一记。
介绍 web 长图之前,先来说一下单屏图片的生成方案,和手机截图不同的是生成的图片不会显示顶部的状态栏、标题栏以及底部的菜单栏,可以满足不同的业务需求。
有的时候我们需要将一个长 Web 网页生成图片分享出去,相似的例子就是手机端的各种便签应用,当便签内容超出一屏时,就需要将所有的内容生成一张长图对外分享出去。
WebView 和其他 View 一样,系统都提供了 draw 方法,可以直接将 View 的内容渲染到画布上,有了画布我们就可以在上面绘制其他各种各种的内容,比如底部添加 Logo 图片,画红线框等等。关于 WebView 生成长图网上已经有很多现成的方案和代码,以下代码是经测试过的稳定版本,供参考。
Android 为了提高滚动等各方面的绘制速度,可以为每一个 View 建立一个缓存,使用View#buildDrawingCache
为自己的 View 建立相应的缓存, 这个 cache 就是一个 bitmap 对象。利用这个功能可以对整个屏幕视图进行截屏并生成 Bitmap ,也可以获得指定的 View 的 Bitmap
对象。这里由于还要在原有的图片上绘制 Logo ,所以直接使用了 WebView 的 draw 方法了。
由于我们的 H5 页面大部分都是运行在微信的 X5 浏览器中,所以为了减少前端的适配工作,我们将腾讯的 X5 浏览器内核引入了 Android 工程中,代替系统原生的 WebView 内核,关于 X5 内核的引入后续还会有专门的文章介绍,敬请期待。
这里需要说明一下如何在 X5 内核下生成 Web 长图,上面代码展示的系统原生 WebView 生成图片的方案,但是在 X5 环境下上述代码就失效了,经过踩坑以及查看 X5 内核源代码,最终我们找到了解决该问题的方法,下面用关键代码来说明一下具体的实现方式。
注:X5 内核生成的长图清晰度比原生 WebView 要差一些,目前还没有太好的解决方案。
三、长图分享
一般我们向各个社交平台上发送的图片都比较小,最大也就是手机屏幕大小的图片,再大的就不多见了。但是也有例外,比如微博的长图、锤子便签的长图等等,如果直接将这些图片通过微信分享 SDK 或者微博分享 SDK 分享出去,就会发现图片基本上都是模糊的,但是将图片发送给 iPhone 手机就可以正常查看,我们只能哀叹 Android 版微信不给力。
微信 SDK 不给力,但是产品体验还是不能丢,怎么办呢?办法还是有的,我们都知道除了各个社交平台自己的分享 SDK ,系统提供了原生分享方案,本质上就是社交平台把目标 Activity 对外暴露了出来,然后第三方 App 就可以根据事先定义好的 Intent 跳转规则唤起社交平台,同时完成数据传输和展示。
好像问题可以完美解决了,但是还是有坑需要接着踩。在 Android 7.0 及以上的版本系统限制了 Intent 传输 file:// 开头的数据,这也就限制了系统原生分享单图,怎么办呢?两种方案,一种是在 7.0 及以上版本上使用微信等分享 SDK ,接受分享图片模糊的现状,另一种是通过反射跳过系统对以 file:// 开头文件在 Intent 中传输的限制,但是这种方式会有风险,毕竟我们不知道未来 Android 会做出什么调整。以下是跳过系统限制的代码片段,供参考。
至此基本上可以满足任意图片大小的分享了。此外经过验证还发现微信分享 Android 版 SDK 对缩略图和分享图的大小都有限制,官方给的指导意见是缩略图小于 32K ,分享图片小于 10M 即可正常分享,但是试验下来这两个值都是理论上限,不要太接近这个上限,如果图片太大,缩略图和分享图都会出现模糊的情况,甚至无法正常分享,当然对于通过系统分享的话就不存在这个限制,图片也比较清晰。
除了图片大小有限制,缩略图的尺寸也是有限制的,这一点官方文档并没有给出,试验结果显示图片尺寸小于等于120x120是比较安全的范围,分享都没有问题。