Android 截取手机屏幕两种实现方案解析
近期在开发的过程中,遇到了一个须要截取屏幕保存为图片的需求,详细为截取webview的视图保存图片。
方法1:首先想到的思路是利用SDK提供的View.getDrawingCache()方法:
public void printScreen(View view) {
String imgPath = "/sdcard/test.png";
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
if (bitmap != null) {
try {
FileOutputStream out = new FileOutputStream(imgPath);
bitmap.compress(Bitmap.CompressFormat.PNG, 100,
out);
} catch (Exception e) {
e.printStackTrace();
}
}
}
这种方法在非常多情况下都是没有问题的。比方说截取imageview,TextView,甚至otherview.getRootView();都没问题。但在WebView上就会出现webview的部分截取完缺少页面里的一些内容的情况。比方说用webview打开这个(https://miqt.github.io/jellyfish/)界面。截取的图片就会有问题。详细表现为网页中游动的水母没有显示在截取的图片上。
方法2:使用Android系统提供的服务Context.MEDIA_PROJECTION_SERVICE。进行截图操作。
Demo源代码:https://github.com/miqt/CapWindow(欢迎star!)
关键部分代码解析:↓
发送截图请求
final MediaProjectionManager projectionManager = (MediaProjectionManager)
getSystemService(Context.MEDIA_PROJECTION_SERVICE);
Intent intent = projectionManager.createScreenCaptureIntent();
startActivityForResult(intent, REQUEST_CODE);
接收返回的结果:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
handleScreenShotIntent(resultCode, data);
}
private void handleScreenShotIntent(int resultCode, Intent data) {
onScreenshotTaskBegan();
final MediaProjectionManager projectionManager = (MediaProjectionManager)
getSystemService(Context.MEDIA_PROJECTION_SERVICE);
final MediaProjection mProjection = projectionManager.getMediaProjection(resultCode, data);
Point size = Utils.getScreenSize(this);
final int mWidth = size.x;
final int mHeight = size.y;
final ImageReader mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat
.RGBA_8888, 2);
final VirtualDisplay display = mProjection.createVirtualDisplay("screen-mirror", mWidth,
mHeight, DisplayMetrics.DENSITY_MEDIUM,
DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION, mImageReader.getSurface(),
null, null);
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader mImageReader) {
Image image = null;
try {
image = mImageReader.acquireLatestImage();
if (image != null) {
final Image.Plane[] planes = image.getPlanes();
if (planes.length > 0) {
final ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * mWidth;
// create bitmap
Bitmap bmp = Bitmap.createBitmap(mWidth + rowPadding / pixelStride,
mHeight, Bitmap.Config.ARGB_8888);
bmp.copyPixelsFromBuffer(buffer);
Bitmap croppedBitmap = Bitmap.createBitmap(bmp, 0, 0, mWidth, mHeight);
saveBitmap(croppedBitmap);//保存图片
if (croppedBitmap != null) {
croppedBitmap.recycle();
}
if (bmp != null) {
bmp.recycle();
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (image != null) {
image.close();
}
if (mImageReader != null) {
mImageReader.close();
}
if (display != null) {
display.release();
}
mImageReader.setOnImageAvailableListener(null, null);
mProjection.stop();
onScreenshotTaskOver();
}
}
}, getBackgroundHandler());
}
这种方法相似使用手机的系统截屏(音量下键+电源键)。可以完美的吧当前原模原样的屏幕截取下来,而且改动保存方法的话甚至可以屏幕录像,但相比于第一种方法。它的缺点是全然和界面上的view没有关系,而且在调用这个服务的时候,会弹出一个权限确认的弹框。另外须要注意。这一方法仅仅能在Android 5.0的系统设备上适用。
总结:
总而言之。这两种方法各有利弊,使用的时候要依据自己的实际需求做出选择。
Android 截取手机屏幕两种实现方案解析的更多相关文章
- Android 的保活的两种解决方案
原文链接:http://blog.csdn.net/pan861190079/article/details/72773549 详细的阐述了 Android 的保活的两种解决方案 —— 由panhao ...
- ADB连接手机的两种方式(usb数据线连接和wifi连接)
ADB(Android Debug Bridge)安卓测试桥,它是连接电脑开发端和安卓设备的桥梁,这个安卓设备可以是真实的安卓手机或者平板,也可以是虚拟的安卓模拟器, 这里介绍ADB连接手机的两种 ...
- 利用adb查看手机设备ip和连接手机的两种方式
电脑安装adb(查看菜鸟adb教程) [cmd]->输入adb devices (设置了path,否则需要 ./路径/adb devices)如图: 查看ip两种方法(可能有更多,目前我还没看到 ...
- Android 抗锯齿的两种方法
Android 抗锯齿的两种方法 (其一:paint.setAntiAlias(ture);paint.setBitmapFilter(true)) 在Android中,目前,我知道有两种出现锯齿 ...
- android emulator启动的两种方法详解
android emulator启动的两种方法详解 转https://blog.csdn.net/TTS_Kevin/article/details/7452237 对于android学习者,模 ...
- k8s的两种网络方案与多种工作模式[flannel与calico]
k8s的两种网络方案与多种工作模式 1. Flannel: flannel有三种工作模式: 1. vxlan(隧道方案) 2. host-gw(路由方案) 2. udp(在用户态实现的数据封装解封装, ...
- [转帖]kubernetes ingress 在物理机上的nodePort和hostNetwork两种部署方式解析及比较
kubernetes ingress 在物理机上的nodePort和hostNetwork两种部署方式解析及比较 https://www.cnblogs.com/xuxinkun/p/11052646 ...
- 【Android】adb connect 手机的两种方式
adb支持两种连接Android系统的方式,USB方式及网络方式.一般android手机及android平板默认会设置为USB方式(直接插数据线的方式). 下边介绍两种方式的切换方式. 1. 背景知识 ...
- Android 高级UI设计笔记23:Android 夜间模式之 两种常用方法(降低屏幕亮度+替换theme)
1. 夜间模式 所谓的夜间模式,就是能够根据不同的设定,呈现不同风格的界面给用户,而且晚上看着不伤眼睛.特别是一些新闻类App实现夜间模式是非常人性化的,增强用户体验. 2. 我根据网上的资料 以及自 ...
随机推荐
- Spring学习总结(6)——Spring之核心容器bean
一.Bean的基础知识 1.在xml配置文件中,bean的标识(id 和 name) id:指定在benafactory中管理该bean的唯一的标识.name可用来唯一标识bean 或给bean起别名 ...
- 背景剪除和OpenCV中的实现
转载请注明出处! ! ! http://blog.csdn.net/zhonghuan1992 背景剪除和OpenCV中的实现 背景与前景都是相对的概念.以快速公路为例:有时我们对快速公路上来来往往的 ...
- 84.setlocale
用法示例 #include <Windows.h> #include <stdio.h> #include<locale.h> void main() { //se ...
- Vijos 1164 曹冲养猪(中国剩余定理)
P1164曹冲养猪 Accepted 标签:三国争霸[显示标签] 描写叙述 自从曹冲搞定了大象以后,曹操就開始捉摸让儿子干些事业,于是派他到中原养猪场养猪,但是曹冲满不高兴.于是在工作中马马虎虎,有一 ...
- FTP、WEB虚拟目录作用
随风原文FTP.WEB虚拟目录作用 在 IIS中,双击您要为之添加虚拟目录的服务以显示其属性表. 单击“目录”选项卡. 单击“添加”. 单击“浏览”从“目录”框中选择一个目录. ...
- 数据结构-堆实现优先队列(java)
队列的特点是先进先出.通常都把队列比喻成排队买东西,大家都非常守秩序,先排队的人就先买东西. 可是优先队列有所不同,它不遵循先进先出的规则,而是依据队列中元素的优先权,优先权最大的先被取出. 这就非常 ...
- amazeui页面分析2
amazeui页面分析2 一.总结 1.弄清结构:这些部分都是一块一块分好了的,掌握结构之后,想替换哪块就替换哪块,想不要哪块就不要哪块,非常简单的 2.一块一块:替换十分简单 3.弄清楚大块之后,然 ...
- linux 查询制定目录的制定内容
//.点为查找当前目录 下 的 所有 *.php 文件里 有 hello 的文件 find . -name "*.php" | xargs grep "hello&quo ...
- 【z02】选择客栈
(hotel.cpp/c/pas) [问题描述] 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照 某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示) ...
- C++ BYTE数组转字符串
第一种情况: BYTE[0]=Ox12 BYTE[1]=0x34 BYTE[2]=0x56 最后要转换成字符串123456 另外一种情况: BYTE[0]=Ox12 BYTE[1]=0x34 BYTE ...