最近在项目中做视频通话的屏幕共享的功能,需要用到屏幕采集的功能,由于5.0以上版本系统有api所以实现比较简单,做5.0以下版本时候真的是很痛苦,一下列举一下我尝试的方法。
方法一:利用SDK提供的View.getDrawingCache()方法。
public static Bitmap capture(Activity activity) {
activity.getWindow().getDecorView().setDrawingCacheEnabled(true);
Bitmap bmp = activity.getWindow().getDecorView().getDrawingCache();
return bmp;
}
缺点:1.只能截取自身程序的屏幕画面
2.无法截取WebView页面,截屏后是白屏
方法二:利用命令行“ScreenCap -P”
adb shell screencap -p /sdcard/litest.png 不需要root权限
在命令窗口中执行 可以 截图成功。
但是在在android 应用中 调用
Runtime. getRuntime().exec("screencap -p /sdcard/litest1.png" ) 获得图片大小为0kb 即截图失败
如果在android 想要截图成功需要先修改 /dev/graphics/fb0 权限 需要root权限
adb shell chmod 777 /dev/graphics/fb0 需要root权限否则不能修改权限
Runtime. getRuntime().exec("chmod 777 /dev/graphics/fb0"); 需要su命令。否则不能修改权限。
方法三:利用系统的隐藏API,Screenshot
SurfaceControl.screenshot()(低版本是Surface.screenshot())是系统内部提供的截屏函数,但是这个函数是@hide的,所以无法直接调用,需要反射调用。我尝试反射调用这个函数,但是函数返回的是null,后面发现SurfaceControl这个类也是隐藏的,所以从用户代码中无法获取这个类。也有一些方法能够调用到这个函数,比如重新编译一套sdk,或者在源码环境下编译apk,但是这种方案兼容性太差,只能在特定ROM下成功运行.
网上提供的解决方式 是仿照vysor的原理来做;
但是实际操作结果如下
在窗口shell命令下调用: 即 abd shell 以后
export CLASSPATH=/data/app/com.example.screencapture-1.apk
exec app_process /system/bin com.example.screencapture.Main 写一个main类,里面利用surfacecontol 截图
可以截图成功
在android 程序中 利用 su命令之后 写入这两条命令可以执行 ,并且与shell命令下执行流程是一样的。
但是 返回的bitmap 为空。 个人认为是权限问题adb 的权限要高于应用,我利用terminal 终端模拟器在手机上实验,结果采集到的图片也是为空。