Uso de SurfaceControl.screenshot() | Solución para devolver nulo después de usar SurfaceControl.screenshot()

Prefacio

SurfaceControl.screenshot()Es el método de captura de pantalla del sistema, pertenece a la API del sistema y no está abierto a los usuarios, por lo que si desea utilizarlo, necesita la firma ( platform.keystorearchivo) del sistema para llamarlo.
En versiones superiores de Android (por ejemplo android 11), si no hay una firma del sistema, incluso si se usa la reflexión, no se puede encontrar un método, se informará una excepción. Sin embargo, si hay una firma del sistema, simplemente llámela directamente.



Antigua forma de usar

Muchos tutoriales en Internet muestran métodos de llamada antiguos, que ya no son aplicables en versiones superiores, como sigue:

  1. Captura de pantalla usando llamada de reflexión
//获取屏幕尺寸
DisplayMetrics mDisplayMetrics = new DisplayMetrics();
float[] dims = {
    
    mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels};
//调用screenshot()
try {
    
    
    Class<?> demo = Class.forName("android.view.SurfaceControl");
    Method method = demo.getDeclaredMethod("screenshot", int.class,int.class);
    mScreenBitmap = (Bitmap) method.invoke(null,(int) dims[0],(int) dims[1]);
} catch (Exception e) {
    
    
    e.printStackTrace();
}
//显示bitmap
ImageView image = findViewById(R.id.image);
image.setImageBitmap(mScreenBitmap);
  1. Llame directamente al método de captura de pantalla para tomar una captura de pantalla
//获取屏幕尺寸
DisplayMetrics mDisplayMetrics = new DisplayMetrics();
float[] dims = {
    
    mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels};
//调用screenshot()
Bitmap mScreenBitmap = SurfaceControl.screenshot((int) dims[0],(int) dims[1]);
//显示bitmap
ImageView image = findViewById(R.id.image);
image.setImageBitmap(mScreenBitmap);


Nuevas formas de utilizar

En versiones posteriores de Android, screenshot(width, height)el método se canceló, por lo que el método de pasar solo dos valores int no funciona .

Entre los parámetros de construcción restantes de captura de pantalla(), screenshot(Rect sourceCrop, int width, int height, int rotation)este método es el más conveniente de usar.
La descripción del parámetro es la siguiente:

parámetro efecto
fuenteCultivo La parte de la pantalla que se va a capturar en un mapa de bits; la persona que llama puede pasarla si no es necesario recortarla new Rect().
ancho Devuelve el ancho deseado del mapa de bits; la pantalla original se reducirá a este tamaño; la persona que llama puede pasar esto si no se requiere escalado 0.
altura Devuelve la altura deseada del mapa de bits; la pantalla original se reducirá a este tamaño; la persona que llama puede pasar esto si no se requiere escalado 0.
rotación Aplique una rotación personalizada en el sentido de las agujas del reloj a la captura de pantalla, es decir Surface.ROTION_0,90,180,270. De forma predeterminada, SurfaceFlinger siempre tomará capturas de pantalla en su orientación vertical original, por lo que esto es útil para devolver capturas de pantalla que son independientes de la orientación del dispositivo.

Por tanto, en el nuevo sistema Android, podemos escribir así:

//调用screenshot()
//参数传入默认的,表示直接截全屏并且不缩放,不裁剪,不旋转
Bitmap mScreenBitmap = SurfaceControl.screenshot(new Rect(), 0, 0, Surface.ROTATION_0);
//显示bitmap
ImageView image = findViewById(R.id.image);
image.setImageBitmap(mScreenBitmap);

Dado que este método no depende de la Actividad, se puede utilizar para lograr el efecto de capturas de pantalla en segundo plano . Sin embargo, cabe señalar que llamar a este método requiere la firma del sistema ( platform.keystore), o agregarandroid:sharedUserId="android.uid.system"



Solución a la captura de pantalla() que siempre devuelve nulo

Si no se informa ningún error después de llamarlo, pero el valor devuelto bitmapes siempre null, puede ser un problema de permisos. La solución es la siguiente:

  1. aumentando AndroidManifest.xml_android:sharedUserId="android.uid.system"
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.xxx"
    android:sharedUserId="android.uid.system">
	...
  1. Si no desea convertir la aplicación en una aplicación del sistema, puede AndroidManifest.xmlagregar permisos separados en
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.xxx">

	<!-- 增加此权限 -->
    <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
	...

Simplemente use uno de los dos métodos anteriores .

Supongo que te gusta

Origin blog.csdn.net/Guan_li_peng/article/details/128345431
Recomendado
Clasificación