注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

风之云的足迹

点击这里添加博客描述

 
 
 

日志

 
 

测试代码中实现Android截屏功能  

2011-09-29 15:16:31|  分类: Android |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

框架的截屏功能是通过framebuffer来实现的,所以我们先来介绍一下framebuffer。

framebuffer介绍
帧缓冲(framebuffer)是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行 读写操作。这种操作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer设备驱动来完成的。
Linux FrameBuffer 本质上只是提供了对图形设备的硬件抽象,在开发者看来,FrameBuffer 是一块显示缓存,往显示缓存中写入特定格式的数据就意味着向屏幕输出内容。所以说FrameBuffer就是一块白板。例如对于初始化为16 位色的FrameBuffer 来说, FrameBuffer中的两个字节代表屏幕上一个点,从上到下,从左至右,屏幕位置与内存地址是顺序的线性关系。
帧缓存有个地址,是在内存里。我们通过不停的向frame buffer中写入数据, 显示控制器就自动的从frame buffer中取数据并显示出来。全部的图形都共享内存中同一个帧缓存。

Android截屏实现思路
Android系统是基于Linux内核的,所以也存在framebuffer这个设备,我们要实现截屏的话只要能获取到framebuffer中的数据,然后把数据转换成图片就可以了,android中的framebuffer数据是存放在 /dev/graphics/fb0 文件中的,所以我们只需要来获取这个文件的数据就可以得到当前屏幕的内容。
现在我们的测试代码运行时候是通过RC(remote controller)方式来运行被测应用的,那就需要在PC机上来访问模拟器或者真机上的framebuffer数据,这个的话可以通过android的ADB命令来实现。

具体实现


/***********************************************************************
  *
  *   ScreenShot.java
  ***********************************************************************/
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.internal.Base64Encoder;
import com.google.common.io.Closeables;
import com.google.common.io.LittleEndianDataInputStream;

/**
 */
public class ScreenShot {

    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {   
        try {
            //分辨率大小,后续可以通过代码来获取到当前的分辨率
            int xResolution = 320;
            int yResolution = 480;
            //执行adb命令,把framebuffer中内容保存到fb1文件中
             Runtime.getRuntime().exec("adb pull /dev/graphics/fb0 C:/fb1");
             //等待几秒保证framebuffer中的数据都被保存下来,如果没有保存完成进行读取操作会有IO异常
             Thread.sleep(15000);
             //读取文件中的数据
             InputStream in = (InputStream)new FileInputStream("C:/fb1");
             DataInput frameBuffer = new LittleEndianDataInputStream(in);
             
             BufferedImage screenImage = new BufferedImage(
                     xResolution, yResolution, BufferedImage.TYPE_INT_ARGB);
                 int[] oneLine = new int[xResolution];
                for (int y = 0; y < yResolution; y++) {
                    //从frameBuffer中计算出rgb值
                    convertToRgba32(frameBuffer, oneLine);
                    //把rgb值设置到image对象中
                    screenImage.setRGB(0, y, xResolution, 1, oneLine, 0, xResolution);
                }
                Closeables.closeQuietly(in);
               
                ByteArrayOutputStream rawPngStream = new ByteArrayOutputStream();
                try {
                      if (!ImageIO.write(screenImage, "png", rawPngStream)) {
                        throw new RuntimeException(
                            "This Java environment does not support converting to PNG.");
                      }
                    } catch (IOException exception) {
                      // This should never happen because rawPngStream is an in-memory stream.
                     System.out.println("IOException=" + exception);
                    }
                byte[] rawPngBytes = rawPngStream.toByteArray();
                String base64Png = new Base64Encoder().encode(rawPngBytes);
               
                File screenshot = OutputType.FILE.convertFromBase64Png(base64Png);
                System.out.println("screenshot==" + screenshot.toString());
                screenshot.renameTo(new File("C:\\screenshottemp.png"));
               
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println(e);
        }
    }
   
   
    public static void convertToRgba32(DataInput frameBuffer, int[] into) {
        try {
            for (int x = 0; x < into.length; x++) {
                try{
                int rgb = frameBuffer.readShort() & 0xffff;
                int red = rgb >> 11;
                red = (red << 3) | (red >> 2);
                int green = (rgb >> 5) & 63;
                green = (green << 2) | (green >> 4);
                int blue = rgb & 31;
                blue = (blue << 3) | (blue >> 2);
                into[x] = 0xff000000 | (red << 16) | (green << 8) | blue;
                }catch (EOFException e){
                    System.out.println("EOFException=" + e);
                }
              }
        } catch (IOException exception) {
            System.out.println("convertToRgba32Exception=" + exception);
      }
    }
   
}

  评论这张
 
阅读(5421)| 评论(4)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018