今天作項目要用到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 但也已經盡力了,先這樣吧!以後會改進的~