Android 工具类 —— 截屏

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<Bitmap> 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<Bitmap> 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<Integer, Bitmap> 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<T> {
    void invoke() {}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值