android 截屏源码分析,Android新姿势:截屏代码整理

柯波
2023-12-01

今天做项目要用到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加上两行权限:

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

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

 类似资料: