android添加截图功能,Android应用开发之Android 5.0及以上编程实现屏幕截图功能的方法...
本文将带你了解Android应用开发Android 5.0及以上编程实现屏幕截图功能的方法,希望本文对大家学Android有所帮助。
本文实例讲述了Android 5.0及以上编程实现屏幕截图功能的方法。分享给大家供大家参考,具体如下:
在Android 5.0,API 21 之前想要截图系统屏幕必须Root才能完成,5.0之后开放了接口,下面看我们是怎么实现的。
一. 涉及到的相关类
1. MediaProjectionManager
官方原话: Manages the retrieval of certain types of {@link MediaProjection} tokens.
这个类通过 Context#getSystemService 中MEDIA_PROJECTION_SERVICE 获取,他的功能就是获取MediaProjection
2. MediaProjection
官方原话:A
token granting applications the ability to capture screen contents
and/or record system audio. The exact capabilities granted depend on
the type of MediaProjection.在这个类中我们能获取到屏幕的内容
3. ImageReader
官方原话:The ImageReader class allows direct application access to image data
rendered into a {@link android.view.Surface}
通过这个类我们可以把Surface转换成图片
二. 上面三个类就可以完成我们截取屏幕图片的操作,那么下面我们将解释他们是怎么合作完成的
1. 首先获取用户授权,截图屏幕需要用户手动授权后才能操作
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void requestCapturePermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
//5.0 之后才允许使用屏幕截图
return;
}
MediaProjectionManager mediaProjectionManager = (MediaProjectionManager)
getSystemService(Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(
mediaProjectionManager.createScreenCaptureIntent(),
REQUEST_MEDIA_PROJECTION);
}
这里必须使用startActivityForResult 因为在createScreenCaptureIntent() 方法中会返回用户授权截取屏幕的结果,用户根据下面弹窗允许或者拒绝
用户选择后在Activity 的onActivityResult 中操作返回的结果data
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_MEDIA_PROJECTION:
if (resultCode == RESULT_OK && data != null) {
FloatWindowsService.setResultData(data);
startService(new Intent(getApplicationContext(), FloatWindowsService.class));
}
break;
}
}
这里我是用FloatWindowsService在桌面上显示一个悬浮按钮,点击截屏,下面我们看在FloatWindowsService 是如何实现截图
2. 截取屏幕内容生成Bitmap
首先创建ImageReader实例
private void createImageReader() {
mImageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 2);
}
然后点击事件中触发startScreenShot()
private void startScreenShot() {
mFloatView.setVisibility(View.GONE);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//获取当前屏幕内容
startVirtual();
}
}, 5);
handler.postDelayed(new Runnable() {
public void run() {
//生成图片保存到本地
startCapture();
}
}, 30);
}
在startVirtual() 方法中我们做一件事,就是获取当前屏幕内容
public void startVirtual() {
if (mMediaProjection != null) {
virtualDisplay();
} else {
setUpMediaProjection();
virtualDisplay();
}
}
与此同时需要获取MediaProjection 实例,而mResultData 是授权后返回的结果
public void setUpMediaProjection() {
if (mResultData == null) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(intent);
} else {
//mResultData是在Activity中用户授权后返回的结果
mMediaProjection = getMediaProjectionManager().getMediaProjection(Activity.RESULT_OK, mResultData);
}
}
最终得到当前屏幕的内容,注意这里mImageReader.getSurface()被传入,屏幕的数据也将会在ImageReader中的Surface中
private void virtualDisplay() {
mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mImageReader.getSurface(), null, null);
}
最后把mImageReader得到的屏幕内容数据转换成图片,在AsyncTask中处理,
Image.Plane中的 buffer 数据并不是完全是Bitmap所需要的,需要注意下面3点
1. Image 设置的图片格式与Bitmap设置的必须一致
2. 缓冲数据存在行间距,所以我们必须去除这些间距
3. Image 使用后必须调用image.close();关闭,否则再次使用会报错
@Override
protected Bitmap doInBackground(Image... params) {
if (params == null || params.length < 1 || params[0] == null) {
return null;
}
Image image = params[0];
int width = image.getWidth();
int height = image.getHeight();
final Image.Plane[] planes = image.getPlanes();
final ByteBuffer buffer = planes[0].getBuffer();
//每个像素的间距
int pixelStride = planes[0].getPixelStride();
//总的间距
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * width;
Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
image.close();
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!
android添加截图功能,Android应用开发之Android 5.0及以上编程实现屏幕截图功能的方法...相关推荐
- android 图片横竖判断_Android应用开发之android 判断ImageView当前显示的是哪一张图片...
本文将带你了解Android应用开发之android 判断ImageView当前显示的是哪一张图片,希望本文对大家学Android有所帮助. 判断ImageView当前显示的是哪一张图片 Java ...
- android webview权限申请_Android应用开发之android 6.0下webview的定位权限设置方法
本文将带你了解Android应用开发android 6.0下webview的定位权限设置方法,希望本文对大家学Android有所帮助. 如下所示: WebView webView = (WebVi ...
- Android之基于xmpp openfire smack开发之Android客户端开发[3]
http://blog.csdn.net/shimiso/article/details/11225873 在上两篇文章中,我们依次介绍openfire部署以及smack常用API的使用,这一节中我们 ...
- Android之基于xmpp openfire smack开发之Android消息推送技术原理分析和实践[4]
http://blog.csdn.net/shimiso/article/details/8156439 前面几篇给大家系统讲解的有关xmpp openfire smack asmack相关的技术和使 ...
- android图片保存形式,Android应用开发之Android ScrollView截图和图片保存到相册的方式...
本文将带你了解Android应用开发之Android ScrollView截图和图片保存到相册的方式,希望本文对大家学Android有所帮助. 1.1首先来看你一种截取屏幕,这种代码有缺陷,只能截取一 ...
- android换肤的实现方案,Android应用开发之Android一键换肤功能实现
本文将带你了解Android应用开发之Android一键换肤功能实现,希望本文对大家学Android有所帮助. < 市面上对数的App都提供换肤功能,这里暂且不讲白天和夜间模式 下图是网易云音乐 ...
- Android自动手绘,Android应用开发之Android 实现手绘功能教程
本文将带你了解Android应用开发Android 实现手绘功能教程,希望本文对大家学Android有所帮助. 布局文件如下. Activity代码如下,其中线的颜色,宽度等属性都可以修改. pack ...
- android签到功能开发,Android应用开发之Android简单实现app每月签到功能
本文将带你了解Android应用开发Android简单实现app每月签到功能,希望本文对大家学Android有所帮助. 本文实例为大家分享了Android实现app每月签到功能的具体代码,供大家参考, ...
- android targetapi版本低,Android应用开发之Android @TargetAPI版本兼容性解析
本文将带你了解Android应用开发Android @TargetAPI版本兼容性解析,希望本文对大家学Android有所帮助. Android @TargetAPI版本兼容性解析,Android ...
最新文章
- 1-flutter 安装步骤
- mysql中添加外键属性_Python将值插入外键属性(MYSQL)
- 微生物组-宏基因组分析第9期(报名直播课免费参加线下2020最后一期)
- No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer解决方法
- you-get 一个下载视频的好工具
- 如果你的船不进来,就游出去迎接它 乔纳森温特斯
- K8S部署工具:KubeOperator集群规划-自动模式
- 学习设计模式 - 六大基本原则之接口隔离原则
- MyEclipse 如何将 jar 包导入项目中
- 计算机学院考勤管理办法,计科学院进一步加强课堂考勤实施意见(试行)
- python嵌套列表操作_python基础(list列表的操作,公共方法,列表嵌套,元祖)...
- 从imdb爬取ml-100k的电影封面
- 脚本文档_创建完美的架构文档脚本
- oracle数据库怎么保存表,oracle从各个表取得数据保存到另一个表
- python现在版本强势英雄_用Python给漫威和DC英雄综合实力排位
- 兜兜转转~~,忘不了的break!! 忘不了的continue!!!!
- 大学计算机专业学高数吗,数学差的学生,大学最好别选这几个专业,不然将来恐难毕业...
- 什么是构造方法,为什么要使用构造方法
- html页面中鼠标悬停更换图片
- 懂商业的技术合伙人(1):你是怎样成为打工仔的
热门文章
- 旷视砸20亿进军AIoT,发布国内首个机器人协作大脑河图
- SystemCenter2012SP1实践(31)P2V迁移故障一则
- CES中国企业被查抄案最新进展:美公司主动撤诉
- android studio中如何设置注释模板
- Hadoop(十二):从源码角度分析Hadoo是如何将作业提交给集群的
- ubuntu 16.04下安装oracle jdk 1.7
- EXT GridPanel
- vector在java中用什么_在java中使用Vector是否安全?
- python 释放变量所指向的内存_通俗易懂的Python垃圾回收机制及内存管理
- ibmmq 通道命令_IBM MQ 从接收通道获取数据