前言
SurfaceControl.screenshot()
是系统的截屏方法,属于系统API,对用户不开放,因此要使用的话需要系统的签名(platform.keystore
文件)才能调用到。
在高版本的android上(例如android 11
),如果没有系统签名,即使用反射也会报找不到方法的异常,但是有系统签名的话,直接调用就行。
旧方法使用
网上不少教程展示的是旧的调用方式,这些调用方式在高版本中已经不适用了,如下:
- 使用反射调用截屏
//获取屏幕尺寸
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);
- 直接调用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
,则可能是权限问题。解决方案如下:文章来源:https://www.toymoban.com/news/detail-495699.html
- 在
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">
...
- 如果你不想将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" />
...
以上两个方法使用一种就行。文章来源地址https://www.toymoban.com/news/detail-495699.html
到了这里,关于SurfaceControl.screenshot()用法 | SurfaceControl.screenshot()使用后返回null的解决方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!