由于工作的关联关系,本文将针对Android screencap的源码进行分析,此文是基础篇,为后续对源码的修改做知识储备。
android4.0之后内置了截图工具screencap,一般位于/system/bin/screencap
源码路径:frameworks/base/cmds/screencap/
usage: screencap [-hp] [-d display-id] [FILENAME] -h: this message -p: save the file as a png. -d: specify the display id to capture, default 0. If FILENAME ends with .png it will be saved as a png. If FILENAME is not given, the results will be printed to stdout.
使用相当简单:
adb shell screencap -p/sdcard/testscreen.png
备注:
如果手机没有连接adb,我们也可以用以下代码去完成调用:
public Boolean DoScreenShot(){ Process process = null; DataOutputStream os = null; try { } catch (Exception e){ return false; }finally { Try { process = Runtime.getRuntime().exec(“su”); os = new DataOutputStream(process.getOutputStream()); os.writeBytes(“serccncap –p ” + strFileFullPath); os.flush(); process.waitFor(); If (os != null) { os.close(); } process.destroy(); } catch (Exception e){ } } return true; }
核心代码:
整个程序最核心的代码就是上图。
获取截图信息的流程是通过ScreenshotClient对象,如果发现ScreenshotClient获取失败则读取/dev/graphics/fb0文件。
不知道/dev/graphics/fb0是什么文件,可以google下。
1、 fb0读取比较容易看懂:(如果有兴趣的话可以继续去看linux内核文件中的显示文件)
2、ScreenshotClient:
后续我们再继续阅读ScreenshotClient类,了解它是如何显示屏幕显示获取的:
ScreenshotClient类位于frameworks/native/libs/gui/SurfaceComposerClient.cpp中。
这个类提供了updata()函数:
从567行来看,该函数是直接调用了SurfaceFlinger服务的代理对象中的captureScreen()函数。
其中getComposerService()函数的源码:
从代码上可以看出,instance.mComposerService是SurfaceFlinger服务的代理对象。
如果有兴趣的话可以继续跟进去里面的代码,会发现上面的第5行代码就是通过getService("SurfaceFlinger", &mComposerService)获取服务代理对象。
说到“SurfaceFlinger”服务,这个服务器是比较庞大的架构。主要的作用是进行UI绘制。(后续可以深入分析)
所以:
Screencap的实现就是通过访问“SurfaceFlinger”服务或者读取fb0文件进行截屏的。
最后我们看看Screencap保存图片的代码:
程序只提供了png后缀的图片格式,如果想要返回其他的图片格式,需要要进行类型type的修改。
1、SkImageEncoder 中的Type 枚举(注意有些android版本是没有完全实现的)
enum Type{ kUnknown_Type, kBMP_Type, kGIF_Type, kICO_Type, kJPEG_Type, kPNG_Type, kWBMP_Type, kWEBP_Type, kKTX_Type, };
2、kDefaultQuality默认值为80 图片的清晰度
如果想提高这个工具的截屏效率,可以通过选择图片格式或者选择图片的质量。