Android 工具类 —— 截屏

雨点打透心脏的1/2处 2022-04-25 03:18 499阅读 0赞

Android 8.0 截屏

  1. /**
  2. * 快照工具
  3. */
  4. public class SnapShotUtil {
  5. /**
  6. * 获取屏幕截图。
  7. */
  8. public static Bitmap getScreen(Activity activity) {
  9. View view = activity.getWindow().getDecorView();
  10. //启用绘制缓存
  11. view.setDrawingCacheEnabled(true);
  12. //构建缓存视图
  13. view.buildDrawingCache();
  14. //获得视图的缓存图像
  15. Bitmap cache = view.getDrawingCache();
  16. //状态栏区只有背景色,却截取不到任何文字,因此要手动裁剪掉
  17. Rect activityRect = new Rect();
  18. //获取当前activity的可见区域
  19. view.getWindowVisibleDisplayFrame(activityRect);
  20. Bitmap bitmap = BitmapUtil.crop(cache, activityRect);
  21. //关闭视图缓存机制
  22. view.setDrawingCacheEnabled(false);
  23. //删除视图缓存
  24. view.destroyDrawingCache();
  25. return bitmap;
  26. }
  27. /**
  28. * 通过系统录屏截图
  29. */
  30. public static void getScreenProjection(FragmentActivity activity, Callback<Bitmap> callback) {
  31. //调用系统服务,会弹出一个是否允许录屏的对话框
  32. MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
  33. Intent intent = mediaProjectionManager.createScreenCaptureIntent();
  34. ActivityLauncher.init(activity).startActivityForResult(intent, (resultCode, data) -> {
  35. MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);
  36. //返回null,说明用户拒绝
  37. if (mediaProjection == null) {
  38. return;
  39. }
  40. Point screenSize = DisplayUtil.getResolution(activity);
  41. /*
  42. The producer output buffer format 0x1 doesn't match the ImageReader's configured buffer format 0x4.
  43. 所以各式只能用8888,不能用565
  44. */
  45. ImageReader imageReader = ImageReader.newInstance(screenSize.x, screenSize.y, PixelFormat.RGBA_8888, 1);
  46. int densityDpi = DisplayUtil.getDensityDpi(activity);
  47. VirtualDisplay virtualDisplay = mediaProjection.createVirtualDisplay("screen-mirror",
  48. screenSize.x,
  49. screenSize.y,
  50. densityDpi,
  51. DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
  52. imageReader.getSurface(),
  53. null,
  54. //传null表示在回调在主线程中执行
  55. null);
  56. //在获取Image的时候,得先暂停1秒左右,不然就会获取失败(原因未知)
  57. SystemClock.sleep(1000);
  58. Image image = imageReader.acquireLatestImage();
  59. Bitmap bitmap = BitmapUtil.fromImage(image);
  60. image.close();
  61. callback.invoke(bitmap);
  62. virtualDisplay.release();
  63. });
  64. }
  65. /*
  66. Android 在5.0 之后支持了实时录屏的功能。
  67. 通过实时录屏我们可以拿到截屏的图像。
  68. 同时可以通过在Service中处理实现后台的录屏。
  69. */
  70. @RequiresApi(Build.VERSION_CODES.O)
  71. public static void getViewBySystem(Activity activity, View view, Callback<Bitmap> callback) {
  72. int width = view.getWidth();
  73. int height = view.getHeight();
  74. //这里只能用8888,不能用其它的,否则一片黑取不到图像
  75. Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888, true);
  76. Window window = activity.getWindow();
  77. final int[] location = new int[2];
  78. view.getLocationInWindow(location);
  79. Rect rect = new Rect(location[0], location[1], location[0] + view.getWidth(), location[1] + view.getHeight());
  80. final Handler handler = new Handler(Looper.getMainLooper());
  81. PixelCopy.request(window, rect, bitmap, copyResult -> {
  82. callback.invoke(copyResult == PixelCopy.SUCCESS ? bitmap : null);
  83. }, handler);
  84. }
  85. /**
  86. * 截取视图
  87. */
  88. public static Bitmap getView(View view) {
  89. view.setDrawingCacheEnabled(true);
  90. view.buildDrawingCache();
  91. Bitmap cache = view.getDrawingCache();
  92. Bitmap bitmap = BitmapUtil.clone(cache);
  93. view.setDrawingCacheEnabled(false);
  94. view.destroyDrawingCache();
  95. return bitmap;
  96. }
  97. /**
  98. * 截取 ScrollView 视图
  99. */
  100. public static Bitmap getRecyclerView(RecyclerView recyclerView, int maxSize) {
  101. RecyclerView.Adapter adapter = recyclerView.getAdapter();
  102. int height = 0;
  103. //取列表项和缓存项中的最小值
  104. int size = Math.min(maxSize, adapter.getItemCount());
  105. //把每个item的绘图缓存存储在LruCache中
  106. LruCache<Integer, Bitmap> bitmapCache = new LruCache<>(maxSize);
  107. for (int i = 0; i < size; i++) {
  108. //手动调用创建和绑定ViewHolder方法,
  109. RecyclerView.ViewHolder holder = adapter.createViewHolder(recyclerView, adapter.getItemViewType(i));
  110. adapter.onBindViewHolder(holder, i);
  111. /*
  112. 测量
  113. MeasureSpec.EXACTLY - 视图应该是这么多像素,无论它实际上有多大。
  114. MeasureSpec.AT_MOST - 如果视图的尺寸较小,则视图可以是此尺寸或更小。
  115. MeasureSpec.UNSPECIFIED - 视图可以是它需要的任何大小,以显示它需要显示的内容。
  116. */
  117. holder.itemView.measure(
  118. View.MeasureSpec.makeMeasureSpec(recyclerView.getWidth(), View.MeasureSpec.EXACTLY),
  119. View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
  120. //布局
  121. holder.itemView.layout(0, 0,
  122. holder.itemView.getMeasuredWidth(),
  123. holder.itemView.getMeasuredHeight());
  124. //开启视图绘制缓存
  125. holder.itemView.setDrawingCacheEnabled(true);
  126. holder.itemView.buildDrawingCache();
  127. Bitmap drawingCache = holder.itemView.getDrawingCache();
  128. Bitmap cacheClone = BitmapUtil.clone(drawingCache);
  129. if (cacheClone != null) {
  130. bitmapCache.put(i, cacheClone);
  131. }
  132. //禁用视图绘制缓存
  133. holder.itemView.setDrawingCacheEnabled(false);
  134. //销毁视图绘制缓存
  135. holder.itemView.destroyDrawingCache();
  136. //获取itemView的实际高度并累加
  137. // height += holder.itemView.getMeasuredHeight();
  138. height += cacheClone.getHeight();
  139. }
  140. //这里只能用8888,不能用其它的,否则一片黑取不到图像
  141. Bitmap dstBitmap = Bitmap.createBitmap(recyclerView.getWidth(), height, Bitmap.Config.ARGB_8888);
  142. Canvas canvas = new Canvas(dstBitmap);
  143. Paint paint = new Paint();
  144. for (int i = 0, top = 0; i < size; i++) {
  145. Bitmap bitmap = bitmapCache.get(i);
  146. canvas.drawBitmap(bitmap, 0, top, paint);
  147. top += bitmap.getHeight();
  148. }
  149. return dstBitmap;
  150. }
  151. /**
  152. * 截取 ScrollView 视图
  153. */
  154. public static Bitmap getScrollView(ScrollView scrollView) {
  155. int height = 0;
  156. //ScrollView理论上只有一个子View
  157. for (int i = 0; i < scrollView.getChildCount(); i++) {
  158. height += scrollView.getChildAt(i).getHeight();
  159. }
  160. //这里只能用8888,不能用其它的,否则一片黑取不到图像
  161. Bitmap bitmap = Bitmap.createBitmap(scrollView.getWidth(), height, Bitmap.Config.ARGB_8888);
  162. Canvas canvas = new Canvas(bitmap);
  163. scrollView.draw(canvas);
  164. return bitmap;
  165. }
  166. }
  167. public interface Callback<T> {
  168. void invoke() {}
  169. }

发表评论

表情:
评论列表 (有 0 条评论,499人围观)

还没有评论,来说两句吧...

相关阅读