Several ways to realize Android screen capture

Android screenshots are divided into four types: View screenshots, WebView screenshots, system screenshots and adb screenshots

image.png

image.png

1. View screenshot

The View screenshot is to capture the current View interface, but other information on the screen, such as the status bar or the interface of other applications, cannot be captured.

1.1 Capture the screen except the navigation bar

    // 开始截屏
    private static byte[] screenshotView() {

        // ⬇⬇⬇ 可直接放入点击事件中 ⬇⬇⬇
        View view = getWindow().getDecorView(); // view可以替换成你需要截图的控件,如父控件 RelativeLayout,LinearLayout
        // view.setDrawingCacheEnabled(true); // 设置缓存,可用于实时截图
        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        view.draw(canvas);
        // view.setDrawingCacheEnabled(false); // 清空缓存,可用于实时截图

        String bitmapString = getBitmapString(bitmap); // 位图转 Base64 String
        // byte[] drawByte = getBitmapByte(bitmap); // 位图转为 Byted

        Log.d("111111 合并>>", "bitmapString ====:" + bitmapString);
        matting_img02.setImageBitmap(bitmap); // ImageView控件直接图片展示截好的图片
        // ⬆⬆⬆ 可直接放入点击事件中 ⬆⬆⬆

        return drawByte;
    }

    // 位图转 Base64 String
    private static String getBitmapString(Bitmap bitmap) {
        String result = null;
        ByteArrayOutputStream out = null;
        try {
            if (bitmap != null) {
                out = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);

                out.flush();
                out.close();

                byte[] bitmapBytes = out.toByteArray();
                result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT); // Base64.DEFAULT会自动换行,传给前端会报错,所以要用Base64.NO_WRAP
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    // 位图转 Byte
    private static byte[] getBitmapByte(Bitmap bitmap) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 参数1转换类型,参数2压缩质量,参数3字节流资源
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        try {
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toByteArray();
    }



1.2 Intercept a certain control or area

// 方法1
private static byte[] screenshotView1() {
  View view = title;
  view.setDrawingCacheEnabled(true);
  view.buildDrawingCache();
  Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
  byte[] drawByte = getBitmapByte(bitmap);
  return drawByte;
}

// 方法2
private static byte[] screenshotView2() {
  View view = title;
  Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
  // 使用 Canvas,调用自定义 view 控件的 onDraw 方法,绘制图片
  Canvas canvas = new Canvas(bitmap);
  dView.draw(canvas);
  byte[] drawByte = getBitmapByte(bitmap);
  return drawByte;
}

2. WebView screen capture

There are four ways to take a screenshot of WebView

2.1 Use the capturePicture() method (deprecated)
private static byte[] screenshotWebView() { Picture picture = webview.capturePicture(); //Create a bitmap Bitmap bitmap = Bitmap.createBitmap(picture.getWidth(), picture.getHeight( ), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); // Draw (the native method will be called to complete the graphics drawing) picture.draw(canvas); byte[] drawByte = getBitmapByte(bitmap); return drawByte ; }








2.2 Use the getScale() method (deprecated)

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 Using the getDrawingCache() method

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

2.4 Using the draw() method

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 Snippet image configuration

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

WebView screenshots may not be able to capture the cavans element, because hardware acceleration is enabled, and the attribute android:hardwareAccelerated="false" can be set in AndroidManifest.xml

Turning off hardware acceleration may cause unexpected behavior on the page

3. System screenshot

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;
// callback
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_MEDIA_PROJECTION && data != null) { if (res ultCode == RESULT_OK) { MediaProjection mediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data); if (mediaProjection == null) { Toast.makeText(this,"A program error occurred: MediaProjection@1",Toast.LENGTH_SHORT).show(); return; } // mediaProjection is the current screen stream } else if (resultCode == RESULT_CANCELED) { Log.d(TAG, "User canceled"); } } }













3.2 Surface (requires root privileges)

Before use:

Add the android:sharedUserId="android.uid.system" attribute in AndroidMenifest.xml.
You need to add a system signature
or root system to the program
. Use the Java reflection mechanism to call the system API Screenshot:

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 (requires root authority)

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 command (requires root privileges)

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 screenshot

$ adb shell
shell@ $ screencap /sdcard/screen.png
shell@ $ exit
$ adb pull /sdcard/screen.png

Guess you like

Origin blog.csdn.net/jun_tong/article/details/129811578