Android12实现静默截屏(系统签名版)

该文章介绍了在Android12系统上实现静默截屏的两种方法,一种是通过SurfaceControl类的反射调用来获取屏幕截图,另一种是使用VirtualDisplay和ImageReader创建虚拟显示来捕获屏幕图像。这两种方法都需要特定的系统权限。
摘要由CSDN通过智能技术生成

静默截屏功能,支持android12系统,需要系统签名,根据需要在AndroidManifest中配置以下权限和声明:

android:sharedUserId="android.uid.system"

<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
<uses-permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT" />

主要代码:

package com.boeyu.test;

import android.app.Service;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
import android.os.Build;
import android.os.IBinder;
import android.os.Process;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;

public class ScreenUtils {

    private static final String TAG = "WALX";

    /**
     * 静默截屏,需要权限android.permission.READ_FRAME_BUFFER
     *
     * @return
     */
    public static Bitmap getScreenshot(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        if (Build.VERSION.SDK_INT >= 31) {
            //android12以上
            try {
                Class SurfaceControl = Class.forName("android.view.SurfaceControl");
                Class DisplayCaptureArgs = Class.forName("android.view.SurfaceControl$DisplayCaptureArgs");
                Class Builder = Class.forName("android.view.SurfaceControl$DisplayCaptureArgs$Builder");
                IBinder displayToken = (IBinder) SurfaceControl.getMethod("getInternalDisplayToken").invoke(null);
                Constructor CBuilder = Builder.getConstructor(IBinder.class);
                Object mBuilder = CBuilder.newInstance(displayToken);
                Object mDisplayCaptureArgs = Builder.getMethod("build").invoke(mBuilder);
                Method captureDisplay = SurfaceControl.getMethod("captureDisplay", DisplayCaptureArgs);
                captureDisplay.setAccessible(true);
                Object mScreenshotHardwareBuffer = captureDisplay.invoke(null, mDisplayCaptureArgs);
                return (Bitmap) mScreenshotHardwareBuffer.getClass().getMethod("asBitmap").invoke(mScreenshotHardwareBuffer);
            } catch (Throwable e) {
                Log.e(TAG, e.toString());
            }
        } else {
            try {
                Class c = Class.forName("android.view.SurfaceControl");
                Method method = c.getMethod("screenshot", Rect.class, int.class, int.class, int.class);
                return (Bitmap) method.invoke(c, new Rect(), 0, 0, wm.getDefaultDisplay().getRotation());
            } catch (Throwable e) {
                Log.e(TAG, e.toString());
            }
        }
        return null;
    }

    /**
     * 方法二,需要权限android.permission.CAPTURE_VIDEO_OUTPUT和android.permission.CAPTURE_SECURE_VIDEO_OUTPUT
     * @param context
     * @return
     */
    public static Bitmap getScreenshot2(Context context){
        VirtualDisplay virtualDisplay = null;
        ImageReader reader = null;
        Image image = null;
        try {
            DisplayMetrics metrics = new DisplayMetrics();
            WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            wm.getDefaultDisplay().getRealMetrics(metrics);
            DisplayManager dm = (DisplayManager) context.getSystemService(Service.DISPLAY_SERVICE);
            reader = ImageReader.newInstance(metrics.widthPixels, metrics.heightPixels, PixelFormat.RGBA_8888, 1);
            int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
            if (Process.myUid() == Process.SYSTEM_UID) {
                flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
            }
            virtualDisplay = dm.createVirtualDisplay("capture_screen", metrics.widthPixels, metrics.heightPixels, metrics.densityDpi, reader.getSurface(), flags);

            int count = 0;
            while (image == null) {
                Thread.sleep(50);
                image = reader.acquireLatestImage();
                if (++count > 10) {
                    break;
                }
            }
            if (image != null) {
                int width = image.getWidth();
                int height = image.getHeight();
                final Image.Plane[] planes = image.getPlanes();
                final ByteBuffer buffer = planes[0].getBuffer();
                int pixelStride = planes[0].getPixelStride();
                int rowStride = planes[0].getRowStride();
                int rowPadding = rowStride - pixelStride * width;
                Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
                bitmap.copyPixelsFromBuffer(buffer);
                return bitmap;
            }
        } catch (Throwable e) {
            Log.e(TAG, e.toString());
        } finally {
            try {
                if (image != null) {
                    image.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if (virtualDisplay != null) {
                    virtualDisplay.release();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值