最近做一個項目,項目中用到顯示屏比較大,3840*1080,為了充分發揮大屏的顯示區域,有一個分屏的功能,將大屏分為兩個小屏,獨立顯示。在實現這個需求的時候使用了虛擬屏來實現小屏。為了過渡效果的平滑,需要做一些切換動畫,其中一個點是要抓取虛擬屏的screenshot。
剛開始我使用了SurfaceControl.screenshot方法:
/**
* Copy the current screen contents into the provided {@link Surface}
*
* @param display The display to take the screenshot of.
* @param consumer The {@link Surface} to take the screenshot into.
* @param width The desired width of the returned bitmap; the raw
* screen will be scaled down to this size.
* @param height The desired height of the returned bitmap; the raw
* screen will be scaled down to this size.
*/
public static void screenshot(IBinder display, Surface consumer,
int width, int height) {
screenshot(display, consumer, new Rect(), width, height, 0, 0, true, false);
}
之所以要IBinder display參數,是因為我要獲取虛擬屏的截屏,而不是default display的截屏,所以我用來SurfaceControl.getBuiltinDisplay(int displayId)的方式獲取display token,結果是screenshot一直獲取的是黑屏,有點疑惑,因為虛擬屏的確是有顯示的,不是黑色的。后面我又用screencap -p -d 3 /data/d3.png 獲取截屏,發現還是黑色的,這樣看來很可能是screenshot出了問題,跟到surfaceflinger里面看了一下,發現surfaceflinger不支持virtualdisplay的截屏,builtinDisplay中根本不包含virtual display,看來這個方法不行。
想來想去,我能拿到創建virtualdisplay的surface,能不能直接從這個surface得到bitmap呢?
/**
* Requests a copy of the pixels from a {@link Surface} to be copied into
* a provided {@link Bitmap}.
*
* The contents of the source will be scaled to fit exactly inside the bitmap.
* The pixel format of the source buffer will be converted, as part of the copy,
* to fit the the bitmap's {@link Bitmap.Config}. The most recently queued buffer
* in the Surface will be used as the source of the copy.
*
* @param source The source from which to copy
* @param dest The destination of the copy. The source will be scaled to
* match the width, height, and format of this bitmap.
* @param listener Callback for when the pixel copy request completes
* @param listenerThread The callback will be invoked on this Handler when
* the copy is finished.
*/
public static void request(@NonNull Surface source, @NonNull Bitmap dest,
@NonNull OnPixelCopyFinishedListener listener, @NonNull Handler listenerThread) {
request(source, null, dest, listener, listenerThread);
}
看上去是可行的.
