今天做项目要用到android截屏功能,一开始我还庆幸看过一些博客的文章,自信能轻松解决。。。- - 结果坑了一天才搞了个差不多的交差。。。哎!

关于android截屏的代码,大致有3种方法,有兴趣的看下去吧。

方法一:

/**
     * 根据view来生成bitmap图片,可用于截图功能
     */
    public static Bitmap getViewBitmap(View v) {
        v.clearFocus(); //
        v.setPressed(false); //
        // 能画缓存就返回false
        boolean willNotCache = v.willNotCacheDrawing();
        v.setWillNotCacheDrawing(false);
        int color = v.getDrawingCacheBackgroundColor();
        v.setDrawingCacheBackgroundColor(0);
        if (color != 0) {
            v.destroyDrawingCache();
        }
        v.buildDrawingCache();
        Bitmap cacheBitmap = v.getDrawingCache();
        if (cacheBitmap == null) {
            return null;
        }
        Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
        // Restore the view
        v.destroyDrawingCache();
        v.setWillNotCacheDrawing(willNotCache);
        v.setDrawingCacheBackgroundColor(color);
        return bitmap;

    }

    /**
     * 保存Bitmap图片为本地文件
     */
    public static void saveFile(Bitmap bitmap, String filename) {
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(filename);
            if (fileOutputStream != null) {
                bitmap.compress(Bitmap.CompressFormat.PNG, 90, fileOutputStream);
                fileOutputStream.flush();
                fileOutputStream.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

网上看了很多文章,大多用的是这样的方法,直接把一个View转换成Bitmap,然后保存到sd卡。

这个方法用起来很简单,saveFile(getViewBitmap(view),filename);一句代码就搞定了。

不过在项目里用上之后坑爹的发现WebView截不了图!!QAQ 好吧,只好无奈的到处找资料。

翻遍百度谷歌找到了这样的代码:

/**
     * 截取webView可视区域的截图
     * @param  webView 前提:WebView要设置webView.setDrawingCacheEnabled(true);
     * @return
     */
    public static Bitmap captureWebViewVisibleSize(WebView webView) {
        Bitmap bmp = webView.getDrawingCache();
        return bmp;
    }
    /**
     * 截取webView快照(webView加载的整个内容的大小)
     * @param  webView
     * @return
     */
    public static Bitmap captureWebView(WebView webView) {
        Picture snapShot = webView.capturePicture();
        Bitmap bmp = Bitmap.createBitmap(snapShot.getWidth(),
                snapShot.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bmp);
        snapShot.draw(canvas);
        return bmp;
    }

不过还是解决不了我的问题,原因我想应该是我的webview是用了anychart的js文件和swf文件来生成图表的,网上也找到一些人情况跟我一样,说是用了swf的网页不能截图。

方法二:

截取当前Activity的视图并保存。这个可以说比方法一更简单,只是不够灵活,因为截的图是整个屏幕,可是我又不要状态栏和标题栏。QAQ

不过如果成功的话,可以把截的图裁剪一下取出自己需要的部分,也是没问题的。可惜这个方法也不能截出WebView的动态图表。

代码给出如下:

/**
     * 截屏
     * @param  activity
     * @return
     */
    public static Bitmap captureScreen(Activity activity) {
        activity.getWindow().getDecorView().setDrawingCacheEnabled(true);
        Bitmap bmp=getWindow().getDecorView().getDrawingCache();
        return bmp;
    }

其实这个方法也算是方法一的延伸,都是用到View的getDrawingCache()方法来获取Bitmap,所以不行也是理所当然的。

方法三:

第三种方法是用FrameBuffer实现的截屏,这才是真正意义上的截图!(哎,加班了1个小时,终于让我找到些眉目了!)

先介绍下FrameBuffer:framebuffer是linux内核对显示的最底层驱动。在一般的linux文件系统中,通过/dev/fb0设备文件来提供给应用程序对framebuffer进行读写的访问。这里,如果有多个显示设备,就将依次出现fb1,fb2,…等文件。而在我们所说的android系统中,这个设备文件被放在了/dev/graphics/fb0,而且往往只有这一个。

(你看懂了吗?反正我看不懂。。。)

至于详细的原理有兴趣的可以去百度“FrameBuffer中获取Android屏幕截图”

下面说我整理的代码,经测试在我的手机上是可以成功截图的,使用了anychart的webview也能截下来。

/**
     * 截屏
     * @param activity
     * @return
     */
    public static Bitmap captureScreen(Activity activity) {
        // 获取屏幕大小:
        DisplayMetrics metrics = new DisplayMetrics();
        WindowManager WM = (WindowManager) activity
                .getSystemService(Context.WINDOW_SERVICE);
        Display display = WM.getDefaultDisplay();
        display.getMetrics(metrics);
        int height = metrics.heightPixels; // 屏幕高
        int width = metrics.widthPixels; // 屏幕的宽
        // 获取显示方式
        int pixelformat = display.getPixelFormat();
        PixelFormat localPixelFormat1 = new PixelFormat();
        PixelFormat.getPixelFormatInfo(pixelformat, localPixelFormat1);
        int deepth = localPixelFormat1.bytesPerPixel;// 位深
        byte[] piex = new byte[height * width * deepth];
        try {
            Runtime.getRuntime().exec(
                    new String[] { "/system/bin/su", "-c",
                            "chmod 777 /dev/graphics/fb0" });
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            // 获取fb0数据输入流
            InputStream stream = new FileInputStream(new File(
                    "/dev/graphics/fb0"));
            DataInputStream dStream = new DataInputStream(stream);
            dStream.readFully(piex);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 保存图片
        int[] colors = new int[height * width];
        for (int m = 0; m < colors.length; m++) {
            int r = (piex[m * 4] & 0xFF);
            int g = (piex[m * 4 + 1] & 0xFF);
            int b = (piex[m * 4 + 2] & 0xFF);
            int a = (piex[m * 4 + 3] & 0xFF);
            colors[m] = (a << 24) + (r << 16) + (g << 8) + b;
        }
        // piex生成Bitmap
        Bitmap bitmap = Bitmap.createBitmap(colors, width, height,
                Bitmap.Config.ARGB_8888);
        return bitmap;
    }

记得在AndroidManifest.xml加上两行权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />

还有需要注意的是,手机需要root权限,没root过的手机我还没试过,但估计是不行的。

所以搞了大半天,还是不满意!又不是每个人的手机都有root权限。。。QAQ 但也已经尽力了,先这样吧!之后会改进的~