今天在浏览 SystemUI 的内容时发现一个截屏服务 TakeScreenshotService,恰好最近在研究 Android 快速截屏的内容,于是迅速找出源码来看了看
通过该服务,找到了 com.android.systemui.GlobalScreenshot,里面有一个方法
void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible) {
...
// Take the screenshot
mScreenBitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
if (mScreenBitmap == null) {
notifyScreenshotError(mContext, mNotificationManager);
finisher.run();
return;
}
...
}
原来它用到了 SurfaceControl 来进行 screenshot,于是尝试了一下该截屏方法和 UiDevice.takeScreenshot 的时间性能比较
long start = SystemClock.uptimeMillis();
Bitmap screenshot = SurfaceControl.screenshot(1920,720);
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream("/sdcard/a.png"));
if (bos != null) {
screenshot.compress(Bitmap.CompressFormat.PNG, 100, bos);
bos.flush();
}
} catch (IOException ioe) {
Ignore
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException ioe) {
// Ignore
}
}
screenshot.recycle();
}
Log.d("UiTest", "cost:" +(SystemClock.uptimeMillis()-start));
start = SystemClock.uptimeMillis();
uiDevice.takeScreenshot(new File("/sdcard/b.png"));
Log.d("UiTest", "cost2:" +(SystemClock.uptimeMillis()-start));
得到的结论是
D UiTest : cost:65
D UiTest : cost2:216
速度快了三倍多。于是又检查了下图片大小和质量,大小不完全一致,但差别不大,图像质量肉眼基本上看不出差别,也即是说该原生方法完全可以替代 UiDevice 的截图方法
另外还发现,参数 width 和 height 如果设置得比实际屏幕小,得到的是一张传入参数大小的图片,但内容是真实完整屏幕压缩变形的图片
同时,对于多屏幕的截屏操作,该类也提供了 API:
Bitmap screenshot(IBinder displayToken, int width, int height)
使用如下参数即可获得第二块屏幕的截图
SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay(
SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI),1920,720);