Android新姿式:截屏代碼整理

 今天作項目要用到android截屏功能,一開始我還慶幸看過一些博客的文章,自信能輕鬆解決。。。- - 結果坑了一天才搞了個差很少的交差。。。哎!java

關於android截屏的代碼,大體有3種方法,有興趣的看下去吧。linux

方法一:android

/**
     * 根據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卡。web

這個方法用起來很簡單,saveFile(getViewBitmap(view),filename);一句代碼就搞定了。canvas

不過在項目裏用上以後坑爹的發現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的網頁不能截圖。ui

方法二:spa

截取當前Activity的視圖並保存。這個能夠說比方法一更簡單,只是不夠靈活,由於截的圖是整個屏幕,但是我又不要狀態欄和標題欄。QAQcode

不過若是成功的話,能夠把截的圖裁剪一下取出本身須要的部分,也是沒問題的。惋惜這個方法也不能截出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 但也已經盡力了,先這樣吧!以後會改進的~

相關文章
相關標籤/搜索