Android屏幕截图

我们在调屏时很多时候会出现花屏的现象,有的可能和屏有关系,有的时候可能和上层软件有关系,那么我们就要去确认了,到底是屏的问题,还是上层软件问题呢,我们可以通过截屏的方法来验证。

好在Android给我们提供了这样的工具screencap,那么首先来看命令help信息:
# screencap -h
usage: screencap [-hp] [-d display-id] [FILENAME]
   -h: this message
   -p: save the file as a png.
   -d: specify the display id to capture, default 0.
If FILENAME ends with .png it will be saved as a png.
If FILENAME is not given, the results will be printed to stdout.

那么我们这里只需要-p选项就可以了,把图片保存到一个目录下,然后就可以把它拉出来查看了。
# screencap -p /sdcard/screenshot.png
$ adb pull /sdcard/screenshot.png .

命令用法很简单的,很有用的一个工具。

除了screencap命令之外,还有个命令screenshot命令,这个命令主要是截取开机logo的命令,猜测是framebuffer并不只是一个缓冲区,有多个(两个),而其中的开机logo缓冲区并没有清掉,screenshot命令则就是截取该缓冲区的数据。

为此,我写了个screenshot.c程序,相当与screenshot命令,只是保存的图片为bmp格式,代码如下:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

struct bitmap_fileheader {
	unsigned short	type;
	unsigned int	size;
	unsigned short	reserved1;
	unsigned short	reserved2;
	unsigned int	off_bits;
} __attribute__ ((packed));

struct bitmap_infoheader {
	unsigned int	size;
	unsigned int	width;
	unsigned int	height;
	unsigned short	planes;
	unsigned short	bit_count;
	unsigned int	compression;
	unsigned int	size_image;
	unsigned int	xpels_per_meter;
	unsigned int	ypels_per_meter;
	unsigned int	clr_used;
	unsigned int	clr_important;
} __attribute__ ((packed));

int saveimage(char *filename, char *fb, int width, int height, int bits_per_pixel)
{
	FILE *fp;
	struct bitmap_fileheader fh;
	struct bitmap_infoheader ih;
	int x, y;

	fp = fopen(filename, "wb");
	if (fp == NULL) {
		printf("can't open file %s\n", filename);
		return -1;
	}

	memset(&fh, 0, sizeof(struct bitmap_fileheader));
	fh.type	= 0x4d42;
	fh.off_bits = sizeof(struct bitmap_fileheader) + sizeof(struct bitmap_infoheader);
	fh.size = fh.off_bits + width * height * (bits_per_pixel / 8);
	fwrite(&fh, 1, sizeof(struct bitmap_fileheader), fp);

	memset(&ih, 0, sizeof(struct bitmap_infoheader));
	ih.size = sizeof(struct bitmap_infoheader);
	ih.width = width;
	ih.height = height;
	ih.planes = 1;
	ih.bit_count = bits_per_pixel;
/*	ih.compression = 0;
	ih.size_image = 0;
	ih.xpels_per_meter = 0;
	ih.ypels_per_meter = 0;
	ih.clr_used = 0;
	ih.clr_important = 0;*/
	fwrite(&ih, 1, sizeof(struct bitmap_infoheader), fp);

/*	fwrite(fb, 1, width * height * (bits_per_pixel / 8), fp);*/

	fb += width * (bits_per_pixel / 8) * (height - 1);
	for (y = 0; y < height; y++, fb -= width * (bits_per_pixel / 8)) {
		fwrite(fb, 1, width * (bits_per_pixel / 8), fp);
	}

	fclose(fp);

	return 0;
}

int main(int argc, char *argv[])
{
	int fd;
	struct fb_var_screeninfo var;
	char *fb;
	int size;

	fd = open("/dev/graphics/fb0", O_RDWR);
	if (fd < 0) {
		printf("can't open fb0!\n");
		return -1;
	}

	ioctl(fd, FBIOGET_VSCREENINFO, &var);
	printf("xres %d yres %d bpp %d\n", var.xres,
			var.yres, var.bits_per_pixel);

	size = var.xres * var.yres * (var.bits_per_pixel / 8);

	fb = (char *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

	saveimage(argv[1], fb, var.xres, var.yres, var.bits_per_pixel);

	munmap(fb, size);

	close(fd);

	return 0;
}
注意该程序并没有考虑bmp图片4字节对齐问题,以及颜色反转问题。

我们还注意screencap命令有个-d选项,该选项默认参数为0,但不使用-d选项时,即参数为0时截取的就是屏当前显示的数据,当使用参数值大于等于1时,screencap命令就同screenshot命令一样,也是开机logo的数据。


// 2015.07.25 add

有的时候,可能只是截图不能满足一些场合,例如瞬时发生的闪屏现象,这个时候需要录像才能看清,好在android也提供了一个命令那就是screenrecord命令,可以通过screenrecord --help查看其具体用法,这里只给出一个简单的用法,例如:

screenrecord /sdcard/demo.mp4

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值