本文将带你了解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及以上编程实现屏幕截图功能的方法...相关推荐

  1. android 图片横竖判断_Android应用开发之android 判断ImageView当前显示的是哪一张图片...

    本文将带你了解Android应用开发之android   判断ImageView当前显示的是哪一张图片,希望本文对大家学Android有所帮助. 判断ImageView当前显示的是哪一张图片 Java ...

  2. android webview权限申请_Android应用开发之android 6.0下webview的定位权限设置方法

    本文将带你了解Android应用开发android 6.0下webview的定位权限设置方法,希望本文对大家学Android有所帮助. 如下所示: WebView webView =   (WebVi ...

  3. Android之基于xmpp openfire smack开发之Android客户端开发[3]

    http://blog.csdn.net/shimiso/article/details/11225873 在上两篇文章中,我们依次介绍openfire部署以及smack常用API的使用,这一节中我们 ...

  4. Android之基于xmpp openfire smack开发之Android消息推送技术原理分析和实践[4]

    http://blog.csdn.net/shimiso/article/details/8156439 前面几篇给大家系统讲解的有关xmpp openfire smack asmack相关的技术和使 ...

  5. android图片保存形式,Android应用开发之Android ScrollView截图和图片保存到相册的方式...

    本文将带你了解Android应用开发之Android ScrollView截图和图片保存到相册的方式,希望本文对大家学Android有所帮助. 1.1首先来看你一种截取屏幕,这种代码有缺陷,只能截取一 ...

  6. android换肤的实现方案,Android应用开发之Android一键换肤功能实现

    本文将带你了解Android应用开发之Android一键换肤功能实现,希望本文对大家学Android有所帮助. < 市面上对数的App都提供换肤功能,这里暂且不讲白天和夜间模式 下图是网易云音乐 ...

  7. Android自动手绘,Android应用开发之Android 实现手绘功能教程

    本文将带你了解Android应用开发Android 实现手绘功能教程,希望本文对大家学Android有所帮助. 布局文件如下. Activity代码如下,其中线的颜色,宽度等属性都可以修改. pack ...

  8. android签到功能开发,Android应用开发之Android简单实现app每月签到功能

    本文将带你了解Android应用开发Android简单实现app每月签到功能,希望本文对大家学Android有所帮助. 本文实例为大家分享了Android实现app每月签到功能的具体代码,供大家参考, ...

  9. android targetapi版本低,Android应用开发之Android @TargetAPI版本兼容性解析

    本文将带你了解Android应用开发Android @TargetAPI版本兼容性解析,希望本文对大家学Android有所帮助. Android   @TargetAPI版本兼容性解析,Android ...

最新文章

  1. 1-flutter 安装步骤
  2. mysql中添加外键属性_Python将值插入外键属性(MYSQL)
  3. 微生物组-宏基因组分析第9期(报名直播课免费参加线下2020最后一期)
  4. No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer解决方法
  5. you-get 一个下载视频的好工具
  6. 如果你的船不进来,就游出去迎接它 乔纳森温特斯
  7. K8S部署工具:KubeOperator集群规划-自动模式
  8. 学习设计模式 - 六大基本原则之接口隔离原则
  9. MyEclipse 如何将 jar 包导入项目中
  10. 计算机学院考勤管理办法,计科学院进一步加强课堂考勤实施意见(试行)
  11. python嵌套列表操作_python基础(list列表的操作,公共方法,列表嵌套,元祖)...
  12. 从imdb爬取ml-100k的电影封面
  13. 脚本文档_创建完美的架构文档脚本
  14. oracle数据库怎么保存表,oracle从各个表取得数据保存到另一个表
  15. python现在版本强势英雄_用Python给漫威和DC英雄综合实力排位
  16. 兜兜转转~~,忘不了的break!! 忘不了的continue!!!!
  17. 大学计算机专业学高数吗,数学差‍的学生,大学最好别选这几个专业,不然将来恐难毕业...
  18. 什么是构造方法,为什么要使用构造方法
  19. html页面中鼠标悬停更换图片
  20. 懂商业的技术合伙人(1):你是怎样成为打工仔的

热门文章

  1. 旷视砸20亿进军AIoT,发布国内首个机器人协作大脑河图
  2. SystemCenter2012SP1实践(31)P2V迁移故障一则
  3. CES中国企业被查抄案最新进展:美公司主动撤诉
  4. android studio中如何设置注释模板
  5. Hadoop(十二):从源码角度分析Hadoo是如何将作业提交给集群的
  6. ubuntu 16.04下安装oracle jdk 1.7
  7. EXT GridPanel
  8. vector在java中用什么_在java中使用Vector是否安全?
  9. python 释放变量所指向的内存_通俗易懂的Python垃圾回收机制及内存管理
  10. ibmmq 通道命令_IBM MQ 从接收通道获取数据