SurfaceControl.screenshot()用法 | SurfaceControl.screenshot()使用后返回null的解决方案

前言

SurfaceControl.screenshot()是系统的截屏方法,属于系统API,对用户不开放,因此要使用的话需要系统的签名(platform.keystore文件)才能调用到。
在高版本的android上(例如android 11),如果没有系统签名,即使用反射也会报找不到方法的异常,但是有系统签名的话,直接调用就行。



旧方法使用

网上不少教程展示的是旧的调用方式,这些调用方式在高版本中已经不适用了,如下:

  1. 使用反射调用截屏
//获取屏幕尺寸
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. 直接调用screenshot方法截屏
//获取屏幕尺寸
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);


新方法使用

在后期的android版本中,已经取消了screenshot(width, height)方法,因此只传入两个int值的方式行不通了

在剩下的screenshot()构造参数中,使用起来最方便的就是screenshot(Rect sourceCrop, int width, int height, int rotation)这个方法。
对于参数说明如下:

参数作用
sourceCrop要捕获到位图中的屏幕部分;如果不需要裁剪,调用者可以传入new Rect()
width返回位图的所需宽度;原始屏幕将缩小到该大小;如果不需要缩放,调用者可以传入0
height返回位图的所需高度;原始屏幕将缩小到该大小;如果不需要缩放,调用者可以传入0
rotation将自定义顺时针旋转应用于屏幕截图,即Surface.ROTION_0,90,180,270。默认情况下,SurfaceFlinger将始终以其原始纵向方向拍摄屏幕截图,因此这对于返回独立于设备方向的屏幕截图非常有用

因此,在新的android系统上,我们可以这样写:

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

由于此方法不依赖于Activity,所以可以用来实现后台截屏的效果。但是要注意的是,调用此方法需要系统的签名(platform.keystore),或者增加android:sharedUserId="android.uid.system"



screenshot()始终返回null的解决方案

如果你调用后不报错,但同时返回的bitmap又一直为null,则可能是权限问题。解决方案如下:

  1. 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. 如果你不想将app变成系统应用,可以在AndroidManifest.xml中增加单独的权限
<?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" />
	...

以上两个方法使用一种就行

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值