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.keystore
archivo) 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:
- 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);
- 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 bitmap
es siempre null
, puede ser un problema de permisos. La solución es la siguiente:
- 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">
...
- Si no desea convertir la aplicación en una aplicación del sistema, puede
AndroidManifest.xml
agregar 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 .