android15 实现截屏功能
在15中要实现截屏,需要通过反射的方式实现
以下的是在低版本中的实现方式
public static Bitmap screenshot(int w, int h) {Class testClass = null;Method saddMethod1 = null;try {testClass = Class.forName("android.view.SurfaceControl");saddMethod1 = testClass.getMethod("screenshot", new Class[]{int.class ,int.class});} catch (ClassNotFoundException e) {e.printStackTrace();return null;}try {return (Bitmap) saddMethod1.invoke(null, new Object[]{w,h});} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}return null;}然而在android9以上需要以下的方式
public static Bitmap screenshot9(int w, int h) {Class testClass = null;Method saddMethod1 = null;try {testClass = Class.forName("android.view.SurfaceControl");saddMethod1 = testClass.getMethod("screenshot", new Class[]{Rect.class,int.class ,int.class, int.class});} catch (ClassNotFoundException e) {e.printStackTrace();return null;}try {return (Bitmap) saddMethod1.invoke(null, new Object[]{new Rect(), w, h, 0});} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}return null;}在android12以上的截图方式如下
private static Bitmap screenshot(int width, int height){DisplayManager mDisplayManager = RcApplication.getApp().getSystemService(DisplayManager.class);final Display display = mDisplayManager.getDisplay(DEFAULT_DISPLAY);DisplayMetrics displayMetrics = new DisplayMetrics();display.getRealMetrics(displayMetrics);int widthPixels = displayMetrics.widthPixels;int heightPixels = displayMetrics.heightPixels;try {Class<?> Display = Class.forName("android.view.Display");Method getAddress = Display.getDeclaredMethod("getAddress");Object address = getAddress.invoke(display);;//DisplayAddressClass<?> DisplayAddress_Physical = Class.forName("android.view.DisplayAddress$Physical");if (!(DisplayAddress_Physical.isInstance(address))) {
//                Log.e(TAG, "Skipping Screenshot - Default display does not have a physical address: " + display);}else{Method getPhysicalDisplayId = DisplayAddress_Physical.getDeclaredMethod("getPhysicalDisplayId");long mPhysicalDisplayId = (long) getPhysicalDisplayId.invoke(address);Class<?> SurfaceControl = Class.forName("android.view.SurfaceControl");Method getPhysicalDisplayToken = SurfaceControl.getDeclaredMethod("getPhysicalDisplayToken", long.class);final IBinder displayToken = (IBinder) getPhysicalDisplayToken.invoke(null, mPhysicalDisplayId);Class<?> SurfaceControl_DisplayCaptureArgs_Builder = Class.forName("android.view.SurfaceControl$DisplayCaptureArgs$Builder");Constructor<?> constructor = SurfaceControl_DisplayCaptureArgs_Builder.getDeclaredConstructor(IBinder.class);Object builder = constructor.newInstance(displayToken);//SurfaceControl_DisplayCaptureArgs_BuilderMethod setSourceCrop = SurfaceControl_DisplayCaptureArgs_Builder.getDeclaredMethod("setSourceCrop", Rect.class);Method setSize = SurfaceControl_DisplayCaptureArgs_Builder.getDeclaredMethod("setSize", int.class, int.class);Method setUseIdentityTransform = SurfaceControl_DisplayCaptureArgs_Builder.getDeclaredMethod("setUseIdentityTransform", boolean.class);Method build = SurfaceControl_DisplayCaptureArgs_Builder.getDeclaredMethod("build");//                builder = setSourceCrop.invoke(builder, new Rect(0,0, widthPixels,heightPixels));builder = setSize.invoke(builder, width, height);//目标分辨率builder = setUseIdentityTransform.invoke(builder, true);//角度设置Object displayCaptureArgs = build.invoke(builder);//SurfaceControl.DisplayCaptureArgsMethod captureDisplay = SurfaceControl.getDeclaredMethod("captureDisplay", displayCaptureArgs.getClass());Object screenshotHardwareBuffer = captureDisplay.invoke(null, displayCaptureArgs);//ScreenshotHardwareBufferif(screenshotHardwareBuffer != null){Class<?> SurfaceControl_ScreenshotHardwareBuffer = Class.forName("android.view.SurfaceControl$ScreenshotHardwareBuffer");Method asBitmap = SurfaceControl_ScreenshotHardwareBuffer.getDeclaredMethod("asBitmap");Bitmap bitmap = (Bitmap) asBitmap.invoke(screenshotHardwareBuffer);return bitmap;}}} catch (Exception e) {e.printStackTrace();}return null;}在android15中的截图实现是参考源码中的实现进行的反射实现,如下
public static Bitmap screenshot15(int w, int h) {int displayId = 0;try {Method getServiceMethod;try {getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", String.class);} catch (Exception e) {e.printStackTrace();return null;}IInterface manager;try {IBinder binder = (IBinder) getServiceMethod.invoke(null, "window");Method asInterfaceMethod = Class.forName("android.view.IWindowManager$Stub").getMethod("asInterface", IBinder.class);manager = (IInterface) asInterfaceMethod.invoke(null, binder);} catch (Exception e) {e.printStackTrace();return null;}// Resolve classes via reflectionClass<?> screenCaptureCls = Class.forName("android.window.ScreenCapture");Class<?> captureArgsCls = Class.forName("android.window.ScreenCapture$CaptureArgs");Class<?> captureArgsBuilderCls = Class.forName("android.window.ScreenCapture$CaptureArgs$Builder");Class<?> screenCaptureListenerCls = Class.forName("android.window.ScreenCapture$ScreenCaptureListener");Class<?> syncListenerCls = Class.forName("android.window.ScreenCapture$SynchronousScreenCaptureListener");// Build CaptureArgs via BuilderObject captureArgsBuilder;try {Constructor<?> builderCtor = captureArgsBuilderCls.getDeclaredConstructor();captureArgsBuilder = builderCtor.newInstance();} catch (NoSuchMethodException e) {// Some builds expose an implicit default ctor onlycaptureArgsBuilder = captureArgsBuilderCls.newInstance();}// Optional width/heighttry {Method setSizeMethod = captureArgsBuilderCls.getDeclaredMethod("setSize", int.class, int.class);captureArgsBuilder = setSizeMethod.invoke(captureArgsBuilder, w, h);} catch (NoSuchMethodException ignored) {// setSize may not exist on some builds}Method buildMethod = captureArgsBuilderCls.getDeclaredMethod("build");Object captureArgs = buildMethod.invoke(captureArgsBuilder);// Create a synchronous listenerMethod createSyncCaptureListener = screenCaptureCls.getDeclaredMethod("createSyncCaptureListener");Object syncListener = createSyncCaptureListener.invoke(null);// Call IWindowManager.captureDisplay(int, CaptureArgs, ScreenCaptureListener)Class<?> iwmCls = manager.getClass();Method captureDisplay = iwmCls.getMethod("captureDisplay", int.class, captureArgsCls, screenCaptureListenerCls);captureDisplay.invoke(manager, displayId, captureArgs, syncListener);// Retrieve buffer via SynchronousScreenCaptureListener.getBuffer()Method getBuffer = syncListenerCls.getDeclaredMethod("getBuffer");Object screenshotBuffer = getBuffer.invoke(syncListener);if (screenshotBuffer == null) {return null;}// Convert buffer to Bitmap via ScreenshotHardwareBuffer.asBitmap()Class<?> shbCls;try {shbCls = Class.forName("android.window.ScreenCapture$ScreenshotHardwareBuffer");} catch (ClassNotFoundException e) {// Fallback name used on some buildsshbCls = Class.forName("android.view.SurfaceControl$ScreenshotHardwareBuffer");}Method asBitmap = shbCls.getDeclaredMethod("asBitmap");Bitmap bmp = (Bitmap) asBitmap.invoke(screenshotBuffer);if (bmp == null) return null;return bmp.copy(Bitmap.Config.ARGB_8888, true);} catch (Throwable e) {Ln.e("Could not capture display via reflection", e);return null;}}