当前位置:   article > 正文

Android 截屏实现的几种方式

android 截屏

Android 截屏分为四种:View 截屏、WebView 截屏、系统截屏 和 adb 截屏

image.png

image.png

1、View 截屏

View 截图是将当前 View 界面截取下来,而对于屏幕上其他信息比如:状态栏或其他应用的界面将无法截取。

1.1 截取除了导航栏之外的屏幕

  1. // 开始截屏
  2. private static byte[] screenshotView() {
  3. // ⬇⬇⬇ 可直接放入点击事件中 ⬇⬇⬇
  4. View view = getWindow().getDecorView(); // view可以替换成你需要截图的控件,如父控件 RelativeLayout,LinearLayout
  5. // view.setDrawingCacheEnabled(true); // 设置缓存,可用于实时截图
  6. Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
  7. Canvas canvas = new Canvas(bitmap);
  8. view.draw(canvas);
  9. // view.setDrawingCacheEnabled(false); // 清空缓存,可用于实时截图
  10. String bitmapString = getBitmapString(bitmap); // 位图转 Base64 String
  11. // byte[] drawByte = getBitmapByte(bitmap); // 位图转为 Byted
  12. Log.d("111111 合并>>", "bitmapString ====:" + bitmapString);
  13. matting_img02.setImageBitmap(bitmap); // ImageView控件直接图片展示截好的图片
  14. // ⬆⬆⬆ 可直接放入点击事件中 ⬆⬆⬆
  15. return drawByte;
  16. }
  17. // 位图转 Base64 String
  18. private static String getBitmapString(Bitmap bitmap) {
  19. String result = null;
  20. ByteArrayOutputStream out = null;
  21. try {
  22. if (bitmap != null) {
  23. out = new ByteArrayOutputStream();
  24. bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
  25. out.flush();
  26. out.close();
  27. byte[] bitmapBytes = out.toByteArray();
  28. result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT); // Base64.DEFAULT会自动换行,传给前端会报错,所以要用Base64.NO_WRAP
  29. }
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. } finally {
  33. try {
  34. if (out != null) {
  35. out.flush();
  36. out.close();
  37. }
  38. } catch (IOException e) {
  39. e.printStackTrace();
  40. }
  41. }
  42. return result;
  43. }
  44. // 位图转 Byte
  45. private static byte[] getBitmapByte(Bitmap bitmap) {
  46. ByteArrayOutputStream out = new ByteArrayOutputStream();
  47. // 参数1转换类型,参数2压缩质量,参数3字节流资源
  48. bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
  49. try {
  50. out.flush();
  51. out.close();
  52. } catch (IOException e) {
  53. e.printStackTrace();
  54. }
  55. return out.toByteArray();
  56. }


1.2 截取某个控件或者区域

  1. // 方法1
  2. private static byte[] screenshotView1() {
  3. View view = title;
  4. view.setDrawingCacheEnabled(true);
  5. view.buildDrawingCache();
  6. Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
  7. byte[] drawByte = getBitmapByte(bitmap);
  8. return drawByte;
  9. }
  10. // 方法2
  11. private static byte[] screenshotView2() {
  12. View view = title;
  13. Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
  14. // 使用 Canvas,调用自定义 view 控件的 onDraw 方法,绘制图片
  15. Canvas canvas = new Canvas(bitmap);
  16. dView.draw(canvas);
  17. byte[] drawByte = getBitmapByte(bitmap);
  18. return drawByte;
  19. }

2、WebView 截屏

WebView 截屏有四种方式

2.1 使用 capturePicture() 方法(已废弃)
private static byte[] screenshotWebView() {
Picture picture = webview.capturePicture();
//创建位图
Bitmap bitmap = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// 绘制(会调用 native 方法,完成图形绘制)
picture.draw(canvas);
byte[] drawByte = getBitmapByte(bitmap);
return drawByte;
}

2.2 使用 getScale() 方法(已废弃)

private static byte[] screenshotWebView() {
float scale = webView.getScale();
int webViewHeight = (int) (webView.getContentHeight()*scale+0.5);
Bitmap bitmap = Bitmap.createBitmap(webView.getWidth(),webViewHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
webView.draw(canvas);
byte[] drawByte = getBitmapByte(bitmap);
return drawByte;
}

2.3 使用 getDrawingCache() 方法

private static byte[] screenshotWebView() {
Bitmap bitmap = webView.getDrawingCache();
byte[] drawByte = getBitmapByte(bmp);
return drawByte;
}

2.4 使用 draw() 方法

private static byte[] screenshotWebView() {
// webView.setDrawingCacheEnabled(true); // 设置缓存
Bitmap bitmap = Bitmap.createBitmap(webView.getWidth(), webView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
webView.draw(canvas);
webView.destroyDrawingCache();
byte[] drawByte = getBitmapByte(bitmap);
// webView.setDrawingCacheEnabled(false); // 清空缓存
return drawByte;
}

2.5 截长图配置

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
WebView.enableSlowWholeDocumentDraw();
}
setContentView(R.layout.activity_webview);

WebView 截图可能截取不到 cavans 元素,原因是开启了硬件加速,可在 AndroidManifest.xml 中设置属性 android:hardwareAccelerated="false"

关闭硬件加速可能导致页面出现意外情况

3、系统截屏

3.1 MediaProjection

public static final int REQUEST_MEDIA_PROJECTION = 10001;
// 申请截屏权限
private void getScreenShotPower() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
MediaProjectionManager mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
if (mProjectionManager != null) {
startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
}
}
}

private MediaProjection mMediaProjection;
// 回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_MEDIA_PROJECTION && data != null) {
if (resultCode == RESULT_OK) {
MediaProjection mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
if (mediaProjection == null) {
Toast.makeText(this,"程序发生错误:MediaProjection@1",Toast.LENGTH_SHORT).show();
return;
}
// mediaProjection 就是当前屏幕流
} else if (resultCode == RESULT_CANCELED) {
Log.d(TAG, "用户取消");
}
}
}

3.2 Surface(需要 root 权限)

使用前需要:

在 AndroidMenifest.xml 中添加 android:sharedUserId="android.uid.system" 属性
需要给程序添加系统签名
或者 root 系统
使用 Java 反射机制,调用系统 API 截图:

private void screenshotSystem() {
Class<?> surfaceClass;
Method method = null;
Bitmap bitmap = null;
try {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
surfaceClass = Class.forName("android.view.SurfaceControl");
} else {
surfaceClass = Class.forName("android.view.Surface");
}
method = surfaceClass.getDeclaredMethod("screenshot", Integer.TYPE, Integer.TYPE);
method.setAccessible(true);
bitmap = (Bitmap)method.invoke((Object)null, webview.getWidth(), webview.getHeight());
byte[] drawByte = getBitmapByte(bitmap);
} catch (ClassNotFoundException e){
e.printStackTrace();
} catch (NoSuchMethodException e){
e.printStackTrace();
} catch (IllegalAccessException e){
e.printStackTrace();
} catch (InvocationTargetException e){
e.printStackTrace();
}
}

3.3 PixelCopy

private void screenshotSystem() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PixelCopy.request(getWindow(), bitmap, new PixelCopy.OnPixelCopyFinishedListener() {
@Override
public void onPixelCopyFinished(int copyResult){
if (PixelCopy.SUCCESS == copyResult) {
byte[] drawByte = getBitmapByte(bitmap);
} else {
// onErrorCallback()
}
}
}, new Handler());
}
}

3.4 framebuffer(需要 root 权限)

String DEVICE_NAME = "/dev/graphics/fb0";
File deviceFile = new File(DEVICE_NAME);
Process localProcess = Runtime.getRuntime().exec("supersu");
String str = "cat " + deviceFile.getAbsolutePath() + "\n";
localProcess.getOutputStream().write(str.getBytes());
return localProcess.getInputStream();

3.5 screencap 命令(需要 root 权限)

private static String getScreenshot(){
Process process = null;
String filePath = "mnt/sdcard/" + System.currentTimeMillis() + ".png";
try {
process = Runtime.getRuntime().exec("su");
PrintStream outputStream = null;
outputStream = new PrintStream(new BufferedOutputStream(process.getOutputStream(), 8192));
outputStream.println("screencap -p " + filePath);
outputStream.flush();
outputStream.close();
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(process != null){
process.destroy();
}
}
return filePath;
}

4、adb 截屏

  1. $ adb shell
  2. shell@ $ screencap /sdcard/screen.png
  3. shell@ $ exit
  4. $ adb pull /sdcard/screen.png
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/740085
推荐阅读
相关标签
  

闽ICP备14008679号