1. FrameBuffer文件介绍
FrameBuffer 文件是 Linux (Android是基于Linux的) 对显示设备的一种抽象设备,相当于显存。Android 的 SurfaceFlinger 想更新屏幕的时候,就会把相应的改变写入到FrameBuffer里。Android 2.x 的时代,显示开机画面的功能也是通过把图像数据写入到FrameBuffer实现的。所以,你可以认为,FrameBuffer里头一定有当前屏幕内容的图像数据。
Android平台上,FrameBuffer 文件的绝对路径一般是: /dev/graphics/fb0 。
所以,如果我们想截图,其中一种方法就是把FrameBuffer里头的图像数据取出来,转换成bitmap,然后存储起来或者给ImageView来显示出来。
2. FrameBuffer文件格式
现在我们知道 FrameBuffer (/dev/graphics/fb0) 文件里头会有当前屏幕的图像数据,取出来就可以了。但是,如果你直接运行这段代码:
public void test() {
byte[] fb_data = new byte[5000000];
FileInputStream fis = null;
try {
fis = new FileInputStream(new File("/dev/graphics/fb0"));
DataInputStream dStream = new DataInputStream(fis);
dStream.readFully(fb_data);
dStream.close();
Bitmap bm = BitmapFactory.decodeByteArray(fb_data, 0, fb_data.length);
mImageView.setBackground(new BitmapDrawable(bm));
} catch (Exception e) {
e.printStackTrace();
}
}
会遇到两个问题:
1. /dev/graphics/fb0 文件会拒绝访问,所以你要让你的程序获取root权限后,才能取到/dev/graphics/fb0里头的数据 ,或者获取 root 权限后把 /dev/graphics/fb0 文件改为所有用户可读 (如何获取root权限,这篇文章暂不讨论)
2. 取到数据后,decode成bitmap,让imageview显示,会花屏,或者索性什么都没显示。
花屏或者什么都不显示,那是因为 FrameBuffer 里头的数据并不是常见的图像数据,直接丢给 BitmapFactory 显示,BitmapFactory 也不知道你这一堆什么玩意儿,所以出来的图像要么花屏,要么什么都不显示。
那我们现在进入正题:FrameBuffer 里头的数据到底是怎么样的?
要弄清这个问题,我们需要在我们的jni代码里执行这段代码:
int fd, ret;
struct fb_fix_screeninfo finfo;
// 打开Framebuffer设备
fd = open("/dev/graphics/fb0", O_RDONLY);
if(fd < 0)
{
<span style="white-space:pre"> </span>LOGD("======Cannot open /dev/graphics/fb0!");
<span style="white-space:pre"> </span>return -1;
}
// 获取Framebuffer 的 fixed info 不变信息
ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
if(ret < 0 )
{
<span style="white-space:pre"> </span>LOGD("Cannot get fixed screen information.");
<span style="white-space:pre"> </span>close(fd);
<span style="white-space:pre"> </span>return -1;
}
通过这段代码,我们获取到了 Framebuffer 设备的 “不变信息” :其实就是一个名叫 fb_fix_screeninfo 的结构体,这个结构体里包含了我们的 Framebuffer 数据的格式。
fb_fix_screeninfo这个结构体定义在 linux/include/linux/fb.h 头 文件里头 ( 虽然这个头文件是linux源码里头找的,但是 fb.h 里头定义的很多东西,Android 都直接沿用了)
定义如下:
struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem */
__u32 type; /* see FB_TYPE_* */
__u32 type_aux;