今天作项目要用到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 但也已经尽力了,先这样吧!以后会改进的~