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