Android 8.0 截屏
/**
* 快照工具
*/
public class SnapShotUtil {
/**
* 获取屏幕截图。
*/
public static Bitmap getScreen(Activity activity) {
View view = activity.getWindow().getDecorView();
//启用绘制缓存
view.setDrawingCacheEnabled(true);
//构建缓存视图
view.buildDrawingCache();
//获得视图的缓存图像
Bitmap cache = view.getDrawingCache();
//状态栏区只有背景色,却截取不到任何文字,因此要手动裁剪掉
Rect activityRect = new Rect();
//获取当前activity的可见区域
view.getWindowVisibleDisplayFrame(activityRect);
Bitmap bitmap = BitmapUtil.crop(cache, activityRect);
//关闭视图缓存机制
view.setDrawingCacheEnabled(false);
//删除视图缓存
view.destroyDrawingCache();
return bitmap;
}
/**
* 通过系统录屏截图
*/
public static void getScreenProjection(FragmentActivity activity, Callback callback) {
//调用系统服务,会弹出一个是否允许录屏的对话框
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
Intent intent = mediaProjectionManager.createScreenCaptureIntent();
ActivityLauncher.init(activity).startActivityForResult(intent, (resultCode, data) -> {
MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
//返回null,说明用户拒绝
if (mediaProjection == null) {
return;
}
Point screenSize = DisplayUtil.getResolution(activity);
/*
The producer output buffer format 0x1 doesn't match the ImageReader's configured buffer format 0x4.
所以各式只能用8888,不能用565
*/
ImageReader imageReader = ImageReader.newInstance(screenSize.x, screenSize.y, PixelFormat.RGBA_8888, 1);
int densityDpi = DisplayUtil.getDensityDpi(activity);
VirtualDisplay virtualDisplay = mediaProjection.createVirtualDisplay("screen-mirror",
screenSize.x,
screenSize.y,
densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
imageReader.getSurface(),
null,
//传null表示在回调在主线程中执行
null);
//在获取Image的时候,得先暂停1秒左右,不然就会获取失败(原因未知)
SystemClock.sleep(1000);
Image image = imageReader.acquireLatestImage();
Bitmap bitmap = BitmapUtil.fromImage(image);
image.close();
callback.invoke(bitmap);
virtualDisplay.release();
});
}
/*
Android 在5.0 之后支持了实时录屏的功能。
通过实时录屏我们可以拿到截屏的图像。
同时可以通过在Service中处理实现后台的录屏。
*/
@RequiresApi(Build.VERSION_CODES.O)
public static void getViewBySystem(Activity activity, View view, Callback callback) {
int width = view.getWidth();
int height = view.getHeight();
//这里只能用8888,不能用其它的,否则一片黑取不到图像
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888, true);
Window window = activity.getWindow();
final int[] location = new int[2];
view.getLocationInWindow(location);
Rect rect = new Rect(location[0], location[1], location[0] + view.getWidth(), location[1] + view.getHeight());
final Handler handler = new Handler(Looper.getMainLooper());
PixelCopy.request(window, rect, bitmap, copyResult -> {
callback.invoke(copyResult == PixelCopy.SUCCESS ? bitmap : null);
}, handler);
}
/**
* 截取视图
*/
public static Bitmap getView(View view) {
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap cache = view.getDrawingCache();
Bitmap bitmap = BitmapUtil.clone(cache);
view.setDrawingCacheEnabled(false);
view.destroyDrawingCache();
return bitmap;
}
/**
* 截取 ScrollView 视图
*/
public static Bitmap getRecyclerView(RecyclerView recyclerView, int maxSize) {
RecyclerView.Adapter adapter = recyclerView.getAdapter();
int height = 0;
//取列表项和缓存项中的最小值
int size = Math.min(maxSize, adapter.getItemCount());
//把每个item的绘图缓存存储在LruCache中
LruCache bitmapCache = new LruCache<>(maxSize);
for (int i = 0; i < size; i++) {
//手动调用创建和绑定ViewHolder方法,
RecyclerView.ViewHolder holder = adapter.createViewHolder(recyclerView, adapter.getItemViewType(i));
adapter.onBindViewHolder(holder, i);
/*
测量
MeasureSpec.EXACTLY - 视图应该是这么多像素,无论它实际上有多大。
MeasureSpec.AT_MOST - 如果视图的尺寸较小,则视图可以是此尺寸或更小。
MeasureSpec.UNSPECIFIED - 视图可以是它需要的任何大小,以显示它需要显示的内容。
*/
holder.itemView.measure(
View.MeasureSpec.makeMeasureSpec(recyclerView.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
//布局
holder.itemView.layout(0, 0,
holder.itemView.getMeasuredWidth(),
holder.itemView.getMeasuredHeight());
//开启视图绘制缓存
holder.itemView.setDrawingCacheEnabled(true);
holder.itemView.buildDrawingCache();
Bitmap drawingCache = holder.itemView.getDrawingCache();
Bitmap cacheClone = BitmapUtil.clone(drawingCache);
if (cacheClone != null) {
bitmapCache.put(i, cacheClone);
}
//禁用视图绘制缓存
holder.itemView.setDrawingCacheEnabled(false);
//销毁视图绘制缓存
holder.itemView.destroyDrawingCache();
//获取itemView的实际高度并累加
// height += holder.itemView.getMeasuredHeight();
height += cacheClone.getHeight();
}
//这里只能用8888,不能用其它的,否则一片黑取不到图像
Bitmap dstBitmap = Bitmap.createBitmap(recyclerView.getWidth(), height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(dstBitmap);
Paint paint = new Paint();
for (int i = 0, top = 0; i < size; i++) {
Bitmap bitmap = bitmapCache.get(i);
canvas.drawBitmap(bitmap, 0, top, paint);
top += bitmap.getHeight();
}
return dstBitmap;
}
/**
* 截取 ScrollView 视图
*/
public static Bitmap getScrollView(ScrollView scrollView) {
int height = 0;
//ScrollView理论上只有一个子View
for (int i = 0; i < scrollView.getChildCount(); i++) {
height += scrollView.getChildAt(i).getHeight();
}
//这里只能用8888,不能用其它的,否则一片黑取不到图像
Bitmap bitmap = Bitmap.createBitmap(scrollView.getWidth(), height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
scrollView.draw(canvas);
return bitmap;
}
}
public interface Callback {
void invoke() {}
}