android菜单截图,Android 截图和录屏

一、Android 截图

Android 截图在这里分为三类:

截取除状态栏的屏幕

截取某个控件或区域

使用 MediaProjection 截图

1.截取除状态栏的屏幕

该方式是使用 View 的 Cache 机制生成 View 的图像缓存保存为 Bitmap。

主要的 API 如下:

void setDrawingCacheEnabled(boolean flag) 开启或关闭 View 的 Cache,设置为 false 后,系统也会自动把原来的 Cache 销毁。

void buildDrawingCache() 创建 Cache,可不调用

Bitmap getDrawingCache() 获取 View 的 Cache 图片

void destroyDrawingCache()销毁 Cache 。若想更新 Cache,必须要调用该方法把旧的 Cache 销毁,才能建立新的。

示例代码

View dView = getWindow().getDecorView();

dView.setDrawingCacheEnabled(true);

dView.buildDrawingCache();

Bitmap bitmap = Bitmap.createBitmap(dView.getDrawingCache());

if(bitmap != null){

imageView.setImageBitmap(bitmap);

}

dView.setDrawingCacheEnabled(false);

2.截取某个控件或区域

该方式的原理和上面一样,都是利用 View 的 Cache 机制,不同点在于,这里的 View 不是 DecorView

示例代码:

View view = ivSrc;

view.setDrawingCacheEnabled(true);

view.buildDrawingCache();

Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());

if (bitmap != null) {

imageView.setImageBitmap(bitmap);

}

view.setDrawingCacheEnabled(false);

还有一种方式是将 View 绘制到 Canvas

View view = ivSrc;

//根据 View 的宽高创建 Bitmap 对象

Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),view.getHeight(), Bitmap.Config.ARGB_8888);

//将以上创建的 Bitmap 指定为要绘制的 Bitmap 作为参数创建画布

Canvas canvas = new Canvas(bitmap);

//将 View 绘制在画布上

view.draw(canvas);

imageView.setImageBitmap(bitmap);

ListView、ScrollView、WebView、RecyclerView 截长图都可以用使用此方法

3、使用 MediaProjection

​ Android 在5.0 之后支持了实时录屏的功能。通过实时录屏我们可以拿到截屏的图像。

大体步骤如下:

初始化一个 MediaProjectionManager 对象

MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);

创建并启动 Intent

Intent captureIntent = mediaProjectionManager.createScreenCaptureIntent();

startActivityForResult(captureIntent, RECORD_REQUEST_CODE);

在 Activity 的 onActivityResult 方法中获取 'MediaProjection' 对象

MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);

创建 ImageReader 对象

//参数1:默认图像的宽度像素

//参数2:默认图像的高度像素

//参数3:图像的像素格式

//参数4:用户想要读图像的最大数量

ImageReader imageReader = ImageReader.newInstance(

metrics.widthPixels, metrics.heightPixels,PixelFormat.RGBA_8888, 1);

ImageReader 类允许应用程序直接访问呈现表面的图像数据创建 ImageReader 对象

主要操作:

getSurface()//得到一个表面,可用于生产这个 ImageReader 的图像

acquireLatestImage() //从ImageReader的队列获得最新的图像,放弃旧的图像。

acquireNextImage() //从ImageReader的队列获取下一个图像

getMaxImages()//最大数量的图像

getWidth() //每个图像的宽度,以像素为单位。

getHeight() //每个图像的高度,以像素为单位。

getImageFormat()//图像格式

close() //释放与此ImageReader相关的所有资源。用完记得关

setOnImageAvailableListener(OnImageAvailableListener listener, Handler handler)//注册一个监听器,当ImageReader有一个新的Image变得可用时候调用。

通过 MediaProjection 创建 VirtualDisplay 对象,把内容渲染给 ImageRaeder 的 Surface 控件

mediaProjection.createVirtualDisplay("Capture",

metrics.widthPixels, metrics.heightPixels, 2,

DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,

imageReader.getSurface(), null, null);

VirtualDisplay 类代表一个虚拟显示器,调用 createVirtualDisplay() 方法,将虚拟显示器的内容渲染在一个 Surface 控件上,当进程终止时虚拟显示器会被自动的释放,并且所有的 Window 都会被强制移除。当不再使用他时,你应该调用 release() 方法来释放资源。

通过 ImageReader 获取 Image 生成 Bitmap

new Thread(){

@Override

public void run() {

while (true) {

Image image = imageReader.acquireNextImage();

//8、

if (image != null) {

Image.Plane[] plane = image.getPlanes();

ByteBuffer buffers = plane[0].getBuffer();

int pixelStride = plane[0].getPixelStride();

int rowStride = plane[0].getRowStride();

int rowPadding = rowStride - pixelStride * metrics.widthPixels;

Bitmap bitmap = Bitmap.createBitmap(metrics.widthPixels + rowPadding

/ pixelStride, metrics.heightPixels,

Bitmap.Config.ARGB_8888);

bitmap.copyPixelsFromBuffer(buffers);

FileUtils.saveBitmap(bitmap);

image.close();

}

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}.start();

Image 为图片数据,Plane 为 Image 的抽象内部类,

image.getPlanes() 获取该图片的像素矩阵,返回值为一个 Plane[] 矩阵

plane.getBuffer() 获取图像数据,getPixelStride() 和 getRowStride() 为获取 Iamge 的一些跨距,经过一系列转换得到图像的尺寸,创建 Bitmap 对象,然后从 Image 的 ByteBuffer 中拷贝像素数据生成 Bitmap

二、MediaProjection 录屏

录屏的实现需要使用 MediaRecoder 类

前面几步同截图类似

1. 初始化一个 MediaProjectionManager 对象

2. 创建并启动 Intent

3. 在 Activity 的 onActivityResult 方法中获取 MediaProjection 对象

4. 初始化 MediaRecorder并准备录制

private void initRecorder() {

mediaRecorder = new MediaRecorder();

width = displayMetrics.widthPixels;

height = displayMetrics.heightPixels;

dpi = displayMetrics.densityDpi;

// 视频最大的尺寸 720 * 1280 ,其他视频尺寸使用屏幕大小

if (dpi > DisplayMetrics.DENSITY_XHIGH) {

width = (orientation == Configuration.ORIENTATION_LANDSCAPE ? 1280 : 720);

height = (orientation == Configuration.ORIENTATION_LANDSCAPE ? 720 : 1280);

}

//如果是横屏,视频输出时旋转90度

mediaRecorder.setOrientationHint(orientation != Configuration.ORIENTATION_LANDSCAPE ? 0 : 90);

// 音频源,这里需要 android.permission.RECORD_AUDIO 权限

mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);

// 视频来源

mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);

// 视频输出格式

mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);

// 录制输出文件

currentVideoFilePath = getRecorderDir();

mediaRecorder.setOutputFile(currentVideoFilePath);

//视频编码格式

mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);

//音频编码格式

mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

// 设置最大时长5分钟

mediaRecorder.setMaxDuration(1 * 60 * 1000);

// 设置视频文件的比特率,经过测试该属性对于视频大小影响最大

mediaRecorder.setVideoEncodingBitRate(1 * 1024 * 1024);

//设置视频分辨率

mediaRecorder.setVideoSize(width, height);

//设置视频帧频率

mediaRecorder.setVideoFrameRate(30);

// 录制发生错误的监听

mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {

@Override

public void onError(MediaRecorder mr, int what, int extra) {

}

});

//记录录制时出现的信息事件

mediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {

@Override

public void onInfo(MediaRecorder mr, int what, int extra) {

}

});

try {

//准备录制

mediaRecorder.prepare();

} catch (IOException e) {

e.printStackTrace();

}

}

5. 创建 VirtualDisplay 以进行录屏

virtualDisplay = mediaProjection.createVirtualDisplay("MainScreen", width, height, dpi,

DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null, null);

把 VirtualDisplay 的渲染目标 Surface 设置为 MediaRecorder 的 getSurface,后面我就可以通过 MediaRecorder 将屏幕内容录制下来

6、开始录制

mediaRecorder.start();

7、停止录制

mediaRecorder.stop();

mediaRecorder.reset();

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值