Android之高效率截图
本文来自网易云社区
作者:孙圣翔
在一张Android手机上截图有好多办法,为了能够高效率的截图,我几乎把所有的方法都尝试了一般。走了好多路,也遇到了好多的问题。
只是想记录下这其中的不容易。
下面所有的测试都是用的我的三星 S4.
屏幕分辨率 1080x1920
androidviewclient
截图速度: 4.5s
最开始截图用的是 google官方提供的纯python库androidviewclient,代码的地址在 https://github.com/dtmilano/AndroidViewClient
基于adb协议,只能在电脑上用。最初被我用在的一个手游自动化测试工具airtest上面。使用它很简单,我写个简单的例子
from com.dtmilano.android.viewclient import ViewClient
c, _ = ViewClient.connectToDeviceOrExit(verbose=False, serialno='10.242.74.241:5555')
s = c.takeSnapshot()
s.save('snapshot.png', 'PNG')
不过这个python库也有坑人的地方。它更新到pypi的时候,所有的历史版本都找不到。使得可以更新过去,但是更新不回来。
最新的版本在有些机器上还跑不了。截图的时候某些手机还会出现图片缺少颜色的问题。
screencap
截图速度: 2.0s
Android手机上自带有一个截图工具,一般都是被放在了/system/bin/screencap下。
使用的时候需要在电脑上安装adb,然后adb shell进入shell环境,使用的时候,需要生成一个临时图片在手机上,然后把照片从手机上传输回来。
可以写成一个批处理脚本
@echo off
adb shell screencap -p /sdcard/snapshot.png
adb pull /sdcard/snapshot.png
adb shell rm /sdcard/snapshot.png
这个样子截图,要比androidviewclient的稳定性好很多。只是需要生成一个临时文件,感觉好别扭。
APK程序直接截图
截图速度: < 1s
stackoverflow上也有不少代码例子。apk必须用java写,意味着我必须学一下java了,买了一本书《Android第一行代码》。
学习了2个多星期,总算入门了。然后写了一个手机app截图。截图代码我就不贴了,这个比较长一点,网上也有很多例子。
这种方法截图效率在1s以内。不过只有在当前App在前台运行的时候才可以截图。就算写成Service也不行。
后来想想,截取不到图也算合理。假如一个App可以截取到其他App运行时的图片,岂不是越权了,用户的隐私还怎么保证。
既然这样,只能放弃了。
ASL
之后有幸看到了google出的一个android-screenshot-library的东西,简称ASL。代码在http://code.google.com/p/android-screenshot-library/
看到这个东西真是让人欣喜若狂。立马下载下来试了试,心情立马就不好了,截图来的图,竟然是黑屏。接着又借了4个手机试验。
结果截图只有一台手机截出来的图能看(还是缺少一个颜色通道的那种)。 看看了代码实现的原理,是直接读取framebuffer。
这个地方我解释下:
在linux中,所有的东西通通都可以映射成文件,连屏幕映射成了文件。android的在/dev/graphics/fb0。
通过读取fb0中的数据,然后在根据一些算法就可以还原出屏幕的图像了。
还有一个库, http://code.google.com/p/android-fb2png/ 看代码原理应该和ASL差不多,不过实现了PC端的一个adb_screenshot的程序。
没法截图怎么用啊,放弃吧。 哎
重回screencap, Golang重写截图程序。
截图速度: 1s
好在android是开源的,直接可以翻到screencap实现的源码。意外的发现他有两种输出格式。
一种是png格式 (耗时1.5s)
还有一种是原始的图片格式(这种原始的格式,跟bmp差不多)。 试验了下,好使400ms
之前看过一个韩国人写的remotedroid <https://code.google.com/p/remoteroid/> 截图速度快的让人震惊。
所以我在想是不是screencap中png的压缩算法有问题。参考下代码中,他输出的格式。用Go语言写了一个转化的程序。
// TakeSnapshot by cmd: /system/bin/screencap
func TakeSnapshot() (img *image.RGBA, err error) {
scrbf = bytes.NewBuffer(nil)
cmd := exec.Command("screencap")
cmd.Stdout = scrbf
if err = cmd.Run(); err != nil {
return
}
var width, height, format int32
binary.Read(scrbf, binary.LittleEndian, &width)
binary.Read(scrbf, binary.LittleEndian, &height)
err = binary.Read(scrbf, binary.LittleEndian, &format)
if err != nil {
return
}
img = image.NewRGBA(image.Rectangle{image.ZP, image.Point{int(width), int(height)}})
return
}
func main(){
s, _ := TakeSnapshot()
out, _ := os.Create("snapshot.png")
defer out.Close()
png.Encode(out, s)
}
利用总共用时1.2s的样子。比之前用screencap 2s快了不少哎。感觉似乎还可以更快点。把png改成jpeg试试。
func main(){
s, _ := TakeSnapshot()
out, _ := os.Create("snapshot.png")
defer out.Close()
jpeg.Encode(out, s, jpeg.Options{60})
}
这种方法变成了1.1s, 感觉似乎还可以更快点。 需要稍微复杂点,需要减少内存申请和拷贝的次数。
// TakeSnapshot by cmd: /system/bin/screencap var SCRBUFLEN int
func TakeSnapshot() (img *image.RGBA, err error) {
var scrbf *bytes.Buffer
if SCRBUFLEN == 0 {
scrbf = bytes.NewBuffer(nil)
} else {
scrbf = bytes.NewBuffer(make([]byte, 0, SCRBUFLEN))
}
cmd := exec.Command("screencap")
cmd.Stdout = scrbf
if err = cmd.Run(); err != nil {
return
}
var width, height, format int32
binary.Read(scrbf, binary.LittleEndian, &width)
binary.Read(scrbf, binary.LittleEndian, &height)
SCRBUFLEN = int(width * height * 4
err = binary.Read(scrbf, binary.LittleEndian, &format)
if err != nil {
return
}
w, h := int(width), int(height)
img = &image.RGBA{scrbf.Bytes(), 4 * w, image.Rect(0, 0, w, h)}
return
}
改完后,变成1.0s了。 终于到了还算可以接受的程度。 整理下代码终于可以让他抛头露面了。
https://github.com/netease/airinput
这就是我在做Android截图的时候,所遇到的大部分问题。要知道截个图是多么的不容易。 另外想说,请一定不要放弃,总会有办法的。
网易云免费体验馆,0成本体验20+款云产品!
更多网易研发、产品、运营经验分享请访问网易云社区。
相关文章:
【推荐】 如何实现最佳的跨平台游戏体验?Unity成亮解密实时渲染
【推荐】 全局脚手架了解一下【fle-cli】
【推荐】 一文了解安卓APP逆向分析与保护机制
Android之高效率截图的更多相关文章
- 【转】Android仿QQ截图应用测试
使用过QQ的同学应该都用过QQ截图,Ctrl+Alt+A进入截图操作,通过拉伸,移动高亮区域的框体可以快速截取我们需要的图片.在android应用中,我们也经常需要截图操作,以下实现了一个类似QQ截图 ...
- Android ADB工具-截图和录制视频(五)
Android ADB工具-截图和录制视频(五) 标签(空格分隔): Android ADB 7. 截图和录制视 命令 功能 adb shell screencap –p <path/file& ...
- 利用monkeyrunner实现Android屏幕连续截图
MonkeyRunner 什么是monkeyrunner monkeyrunner工具提供了一个API,使用此API写出的程序可以在Android代码之外控制Android设备和模拟器.通过monke ...
- [Android] 拍照、截图、保存并显示在ImageView控件中
近期在做Android的项目,当中部分涉及到图像处理的内容.这里先讲述怎样调用Camera应用程序进行拍照,并截图和保存显示在ImageView控件中以及遇到的困难和解决方法. PS:作者购买 ...
- python Windows下的android设备截图工具
目录 界面版 命令行版 界面版 利用python的wx库写个ui界面,用来把android设备的截图输出到电脑屏幕,前提需要安装adb,涉及到的python库也要安装.代码如下: #!/usr/bin ...
- Python写一个Windows下的android设备截图工具
界面版 利用python的wx库写个ui界面,用来把android设备的截图输出到电脑屏幕,前提需要安装adb,涉及到的python库也要安装.代码如下: import wx,subprocess,o ...
- Python实现对Android截图
背景: 测试过程中,总是需要对Android设备进行截图,然后在截图中标注问题描述: 手动方式: 1.使用adb scrrencap /sdcard/screen.png 命令对Android设备进行 ...
- Android开发者资源大汇总
本文总结了最新的Android开发资源.下面列出的资源都是常用的,每个Android程序员都应该知道,能大大方便App开发.Enjoy~ 来源:Android开发周刊 中文的Android开发信息,资 ...
- Genymotion - 强大好用高性能的 Android 模拟器 (在电脑流畅运行APK安卓软件游戏的利器)
随着 Android 系统的应用和游戏越来越丰富,甚至有些比起Windows.Mac上的软件更加好用好玩,因此很多人都希望能在电脑上也能玩到安卓的游戏或APP. 我们曾推荐过 BlueStacks,而 ...
随机推荐
- JAVA分包下项目部分代码存储
一.注册时姓名去重和符合汉字格式: // 新用户申请加入 public void NewHuman() { System.out.println("========新会员申请加入页面==== ...
- css3Transitions 实现的鼠标经过图标位移、旋转、翻转、发光、淡入淡出等多种特效
HTML如下: 1 <div class="container"> 3 <!--特效1 --> <section id="set-1&q ...
- 邮箱/邮件地址的正则表达式及分析(JavaScript,email,regex)
简言 在做用户注册时,常会用到邮箱/邮件地址的正则表达式.本文列举了几种方案,大家可以根据自己的项目情况,选择最适合的方案. 方案1 (常用) 规则定义如下: 以大写字母[A-Z].小写字母[a-z] ...
- bootstrap fileinput 上传文件
最近用到文件上传功能, 说实话:以前遇到过一次,COPY了别人的代码 结束! 这次又要用,可是看到别人很酷的文件上传功能,心痒了! 好吧.简单的办法,找控件: bootstrap fileinput ...
- 织梦dedecms后台登陆密码充值工具
下载后解压,根据自己语言版本,把文件radminpass.php放入网站根目录下执行即可 点击下载:织梦dedecms后台登陆密码充值工具
- Android中的GreenDao框架修改数据库的存储路径
目前android中比较热门的数据库框架有greenDAO.OrmLite.AndrORM,其中我比较喜欢用GreenDao,其运行效率最高,内存消耗最少,性能最佳.具体怎么使用GreenDao,网上 ...
- 中国区 Azure 服务和定价模式概述
由世纪互联运营的 Microsoft Azure 是第一个在中国正式商用,符合中国政府相关法规要求的国际化公有云服务.本文剖析了由世纪互联运营的 Microsoft Azure 的运营模式.采购模式. ...
- 洛谷 P2038 无线网络发射器选址
题目描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129 条东西向街道和129 条南北向街道所形成的网格状,并且相邻 ...
- 将SQL2008升级为SQL2008 r2
我的SQL2008版本信息 Microsoft SQL Server Management Studio 10.0.1600.22 ((SQL_PreRelease).080709-1414 ...
- Windows无法停用设备,原因是某个程序正在使用它...
有时候,当我们用完U盘需要弹出是,会出现“Windows无法停用设备,原因是某个程序正在使用它…”的黄色警告,很无奈.不过可以通过一些方法进行解决(win10版): 1. 打开“文件资源管理器”,选择 ...