android后台截屏踩坑记录
场景:android11 java场景,前端为arkui-x,所以后端activity无view。
很多方面是使用activity来获取view进行截屏,直接pass。
1、使用Android 的 adb 命令来截屏,性能不行
参考如下:
Android后台截屏功能_安卓开发 后台截图-CSDN博客
public String screenShot() {
Log.i(TAG, "screenShot!");
@SuppressLint("SdCardPath")
String capFile = "/sdcard/AIUI/ocr/pic.png";
String cmd = "screencap -p " + capFile;
CmdUtils.fetchRoot(cmd);
return capFile;
}
CmdUtils.fetchRoot是使用root权限执行adb shell命令。
因为adb命令是采用screencap,保存到文件。过程中启动了一个独立进程。
后续流程再读取文件来使用,相当于绕了一些弯路。
在1280x720分辨率下,耗时800m左右。
2、screenshot截屏
有人推荐了SurfaceControl.screenshot()
参考如下:SurfaceControl.screenshot()用法 | SurfaceControl.screenshot()使用后返回null的解决方案-CSDN博客
1)坑1:帖子上的旧方法反射和直接调用,新方法直接调用都不行,猜测是android版本不同。
上网查询android11的SurfaceControl.screenshot的参数,介绍都是4个参数或五个参数,与新方法一致。
灵机一动,用旧方法的反射写法,结合新方法的四个参数,如下:
public byte[] screenShot() {
Log.i(TAG, "screenShot!");
try {
Class<?> demo = Class.forName("android.view.SurfaceControl");
Method method = demo.getDeclaredMethod("screenshot", Rect.class, int.class, int.class, int.class);
Bitmap tbitmap = (Bitmap) method.invoke(null, new Rect(), 0, 0, Surface.ROTATION_0);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
tbitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
byte[] o = null;
return o;
}
}
日志报错如下:
2024-10-18 17:02:28.963 10884-10884 OcrUtil com.example.helloworld I screenShot!
2024-10-18 17:02:28.965 183-199 SurfaceFlinger surfaceflinger E Permission Denial: can't read framebuffer pid=10884, uid=10125
2024-10-18 17:02:28.960 10884-10884 Thread-127 com.example.helloworld W type=1400 audit(0.0:32721): avc: granted { read } for name="if_inet6" dev="proc" ino=4026532556 scontext=u:r:platform_app:s0:c512,c768 tcontext=u:object_r:proc_net:s0 tclass=file app=com.example.helloworld
2024-10-18 17:02:28.965 10884-10884 SurfaceFlinger com.example.helloworld E captureScreen failed to transact: -1
2024-10-18 17:02:28.966 10884-10884 SurfaceControl com.example.helloworld W Failed to take screenshot
2024-10-18 17:02:28.966 10884-10884 System.err com.example.helloworld W java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
2024-10-18 17:02:28.967 10884-10884 System.err com.example.helloworld W at com.example.helloworld.ocr.OcrUtil.screenShot2(OcrUtil.java:281)
说明是framebuffer权限问题。
2)坑2:增加系统签名manifest下android:sharedUserId="android.uid.system",结果不生效。
检查manifest文件,发现在作其他需求时,在application下已经加了android:sharedUserId="android.uid.system",怀疑有冲突,删除application下语句。测试成功。
多次测试,相同分辨率下,截屏时间在500ms-600ms。
更多推荐

所有评论(0)