Android5.0免Root截屏,录屏
http://blog.csdn.net/wds1181977/article/details/52174840
MediaProjection介绍
MediaProjection可以用来捕捉屏幕,具体来说可以截取当前屏幕和录制屏幕视频。MediaProjection由MediaProjectionManager来管理和获取。
使用步骤
首先获取MediaProjectionManager,和其他的Manager一样通过 Context.getSystemService() 传入参数MEDIA_PROJECTION_SERVICE获得实例。
接着调用MediaProjectionManager.createScreenCaptureIntent()弹出dialog询问用户是否授权应用捕捉屏幕,同时覆写onActivityResult()获取授权结果。
如果授权成功,通过MediaProjectionManager.getMediaProjection(int resultCode, Intent resultData)获取MediaProjection实例,通过MediaProjection.createVirtualDisplay(String name, int width, int height, int dpi, int flags, Surface surface, VirtualDisplay.Callback callback, Handler handler)创建VirtualDisplay实例。实际上在上述方法中传入的surface参数,是真正用来截屏或者录屏的。
截屏
截屏这里用到ImageReader类,这个类的getSurface()方法获取到surface直接传入MediaProjection.createVirtualDisplay()方法中,此时就可以执行截取。通过ImageReader.acquireLatestImage()方法即可获取当前屏幕的Image,经过简单处理之后即可保存为Bitmap。
private void startCapture() {
mImageName = System.currentTimeMillis() + ".png";
Log.e(TAG, "image name is : " + mImageName);
Image image = mImageReader.acquireLatestImage();
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();
if (bitmap != null) {
Log.e(TAG, "bitmap create success ");
try {
File fileFolder = new File(mImagePath);
if (!fileFolder.exists())
fileFolder.mkdirs();
File file = new File(mImagePath, mImageName);
if (!file.exists()) {
Log.e(TAG, "file create success ");
file.createNewFile();
}
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
Log.e(TAG, "file save success ");
Toast.makeText(this.getApplicationContext(), "截图成功", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
}
录屏
录屏需要用到上篇博文中的MediaCadec,这个类将原始的屏幕数据编码,在通过MediaMuxer分装为mp4格式保存。MediaCodec.createInputSurface()获取一个surface对象讲起传入MediaProjection.createVirtualDisplay()即可获取屏幕原始多媒体数据,之后读取MediaCodec编码输出数据经过MediaMuxer封装处理为mp4即可播放,实现录屏。
private void recordVirtualDisplay() {//循环多去编解码器输出数据经过处理保存为mp4
while (!mIsQuit.get()) {
int index = mMediaCodec.dequeueOutputBuffer(mBufferInfo, 10000);
Log.i(TAG, "dequeue output buffer index=" + index);
if (index == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {//后续输出格式变化
resetOutputFormat();
} else if (index == MediaCodec.INFO_TRY_AGAIN_LATER) {//请求超时
Log.d(TAG, "retrieving buffers time out!");
try {
// wait 10ms
Thread.sleep(10);
} catch (InterruptedException e) {
}
} else if (index >= 0) {//有效输出
if (!mMuxerStarted) {
throw new IllegalStateException("MediaMuxer dose not call addTrack(format) ");
}
encodeToVideoTrack(index);
mMediaCodec.releaseOutputBuffer(index, false);
}
}
}
private void encodeToVideoTrack(int index) {//输出数据为mp4文件
ByteBuffer encodedData = mMediaCodec.getOutputBuffer(index);
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {//是特定格式信息等配置数据,不是媒体数据
// The codec config data was pulled out and fed to the muxer when we got
// the INFO_OUTPUT_FORMAT_CHANGED status.
// Ignore it.
Log.d(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG");
mBufferInfo.size = 0;
}
if (mBufferInfo.size == 0) {
Log.d(TAG, "info.size == 0, drop it.");
encodedData = null;
} else {
Log.d(TAG, "got buffer, info: size=" + mBufferInfo.size
+ ", presentationTimeUs=" + mBufferInfo.presentationTimeUs
+ ", offset=" + mBufferInfo.offset);
}
if (encodedData != null) {//存在编码数据
encodedData.position(mBufferInfo.offset);
encodedData.limit(mBufferInfo.offset + mBufferInfo.size);
mMuxer.writeSampleData(mVideoTrackIndex, encodedData, mBufferInfo);//写入
Log.i(TAG, "sent " + mBufferInfo.size + " bytes to muxer...");
}
}
private void resetOutputFormat() {
// should happen before receiving buffers, and should only happen once
if (mMuxerStarted) {
throw new IllegalStateException("output format already changed!");
}
MediaFormat newFormat = mMediaCodec.getOutputFormat();
Log.i(TAG, "output format changed.\n new format: " + newFormat.toString());
mVideoTrackIndex = mMuxer.addTrack(newFormat);
mMuxer.start();
mMuxerStarted = true;
Log.i(TAG, "started media muxer, videoIndex=" + mVideoTrackIndex);
}
附录参考
Android5.0免Root截屏,录屏的更多相关文章
- DXGI快速截屏录屏技术
DXGI快速截屏录屏技术 概述 很多地方都需要用到截屏/录屏技术,比如桌面直播,桌面录制等等.在微软Windows平台,有很多截屏的接口,不过大多数性能并不理想,Windows8以后微软引入了一套 ...
- 超便携式截屏录屏软件FastStone Capture
超便携式截屏录屏软件FastStone Capture
- (024)[工具软件]截屏录屏软件FSCapture(转)
该软件比 Snipaste 增加的功能有滚动截图和屏幕录制. 原文地址:https://www.appcgn.com/faststone-capture.html FastStoneCapture,简 ...
- android 调用 screenrecord 实现录屏
首先要说明的是并未实现,本文讲一下自己的思路. adb 使用shell 命令 screenrecord 可录屏. 自己写了个app,通过Process p = Runtime.getRuntime() ...
- iphone手机怎么录屏 两种方法任你挑选
iphone手机怎么录屏呢?苹果手机拥有独特的Airlay镜像投屏,AirPlay的工作原理是当iPhone或IPAD与支持AirPlay技术的硬件,比如Apple TV等设备处在同一个wife的情况 ...
- Android5.0以上版本录屏实现
我录屏的方式是分别录制音频和视频,最后合并成mp4格式,比较麻烦,因为网上完整的教程比较少,所以我打算写一个完整版的,照着我的代码写完之后,至少是能够实现功能的,而不是简单的介绍下用法. 1既然是录制 ...
- android手机截屏、录屏
1. 手动截屏,通过其他第三方软件发送截图,或者从手机取出截图 2. 使用命令截图,将截图保存到手机,再拉取到电脑 #!/bin/sh #运行 sh screenshot name picName=$ ...
- Android 禁止截屏、录屏 — 解决PopupWindow无法禁止录屏问题
项目开发中,为了用户信息的安全,会有禁止页面被截屏.录屏的需求. 这类资料,在网上有很多,一般都是通过设置Activity的Flag解决,如: //禁止页面被截屏.录屏 getWindow().add ...
- 搭建前端监控系统(六)JS截屏和录屏篇
怎样定位前端线上问题,一直以来,都是很头疼的问题,因为它发生于用户的一系列操作之后.错误的原因可能源于机型,网络环境,接口请求,复杂的操作行为等等,在我们想要去解决的时候很难复现出来,自然也就无法解决 ...
随机推荐
- N32903系列的基础知识(1)
N32903U1DN使用ARM926EJ-S内核,其内部集成的JPEG编解码器.CMOS摄像头接口.32通道的声音处理单元(SPU).ADC.DAC等不仅可以满足各种的应用需求,还能减少生产方面的物料 ...
- lua常用操作
1 .Lua生成随机数: Lua 生成随机数需要用到两个函数:math.randomseed(xx), math.random([n [, m]]) 1. math.randomseed(n) 接收一 ...
- 如何提高AJAX客户端响应速度
AJAX的出现极大的改变了Web应用客户端的操作模式,它使的用户可以在全心工作时不必频繁的忍受那令人厌恶的页面刷新.理论上AJAX技术在很大的程度上可以减少用户操作的等待时间,同时节约网络上的数据流量 ...
- poj_3977 折半枚举
题目大意 给定N(N<=35)个数字,每个数字都<= 2^15. 其中一个或多个数字加和可以得到s,求出s的绝对值的最小值,并给出当s取绝对值最小值时,需要加和的数字的个数. 题目分析 需 ...
- poj_2352 Treap
题目大意 对于二维平面上的n个点,给出点的坐标.定义一个点A覆盖的点的个数为满足以下条件的点B的个数:点B的x <= 点A的x坐标,点B的y坐标 <= 点A的y坐标. 给出N个点的 ...
- Java三方---->excel框架之POI的使用一
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能.pdf框架之IText的使用,参见我的博客:Java ...
- springjdbc的批量操作
这里主要是看的官方文档,如何翻译: NamedParameterJdbcTemplate The NamedParameterJdbcTemplate class adds support for p ...
- LeetCode——House Robber
Description: You are a professional robber planning to rob houses along a street. Each house has a c ...
- 搭建FastDFS
---恢复内容开始--- FastDFS是用c语言编写的一款开源的分布式文件系统.FastDFS为互联网量身定制,充分考虑了冗余备份.负载均衡.线性扩容等机制,并注重高可用.高性能等指标,使用Fast ...
- Vue 学习顺序
起步: 1.扎实的 JavaScript / HTML / CSS 基本功,ES6 最好过一遍 2.通读官方教程 (guide) 的基础篇.不要用任何构建工具,就只用最简单的 <script&g ...