Android L新增了MediaProjection录屏的api,捣鼓了大半天,照着github上的demo撸了一遍代码,梳理梳理。
录屏实现依赖MediaProjectionManager
通过
mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE)
拿到是实例
然后创建intent,并startActivityForResult

Intent intent = mediaProjectionManager.createScreenCaptureIntent();startActivityForResult(intent, 123);

在onActvitiyResult()中拿到MediaProjection实例

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode == RESULT_OK && requestCode == 123) {mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);if (mediaProjection != null ) {mRecorder = new ScreenRecorder(mWidth, mHeight, mediaProjection, mDensty);}new Thread() {@Overridepublic void run() {mRecorder.startRecorder();}}.start();btnRecorder.setText("停止录屏");moveTaskToBack(true);}}

录屏很消耗资源,另起一个线程操作

前面的这些步骤呢,主要目的就是一个,开启录屏。

然后,通过MediaProjection实例创建一个虚拟屏幕,剩下的工作主要就是通过MediaCodec,MediaMuxer
将virtualDisplay的进行编码输出到MP4文件中。
思路还是比较简短的,但是呢,我也是踩了不少坑,之前完全不熟悉相关的API只能一遍一遍照着demo撸。
归纳一下实现步骤
1.拿到MediaProjectionManager服务 getSystemService();
2.创建intent,并启动 mediaprojectionmanager.createCpatureIntent();
3.初始化编码器 MediaCodec.createEncoderByType(), 并创建一个suface
mEncoder.createInputSuface()
启动编码器,mEncoder.start();
4.使用suface创建虚拟屏幕 mediaprojection.createVirtualDisplay()
5.创建一个混合器,MediaMuxer;
6.编码并输出。

具体代码

1.拿到MediaProjectionManager服务 getSystemService();

mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);

2.创建intent,并启动 mediaprojectionmanager.createCpatureIntent();

Intent intent = mediaProjectionManager.createScreenCaptureIntent();startActivityForResult(intent, 123);

拿到mediaprojection对象

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode == RESULT_OK && requestCode == 123) {mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data);if (mediaProjection != null ) {mRecorder = new ScreenRecorder(mWidth, mHeight, mediaProjection, mDensty);}new Thread() {@Overridepublic void run() {mRecorder.startRecorder();}}.start();btnRecorder.setText("停止录屏");moveTaskToBack(true);}}

ScreenRecorder构造方法主要是进行了传值工作

    public ScreenRecorder(int mWidth, int mHeight, MediaProjection mediaProjection, int mDensty) {this.mWidth = mWidth;this.mHeight = mHeight;this.mediaProjection = mediaProjection;this.mDensty = mDensty;File file = new File(savePath);if (!file.exists()) {file.mkdirs();}}

在onActivityResult中 另起一个线程调用了startRecorder()方法
看代码

    public void startRecorder() {prepareRecorder();startRecording();}

在prepareRecorder()中初始化编码器,并设置一些参数
设置了bit率,影响清晰度的4000000-6000000b比较合适
framerate 帧率 就是常说的fps
其他的设置还是看google文档吧,我也不是特别清楚,还在学习中

private void prepareRecorder() {mBufferInfo = new MediaCodec.BufferInfo();  //元数据,描述bytebuffer的数据,尺寸,偏移//创建格式化对象 MIMI_TYPE 传入的 video/avc 是H264编码格式MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);int frameRate = 45; format.setInteger(MediaFormat.KEY_BIT_RATE, 3000000);format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);format.setInteger(MediaFormat.KEY_CAPTURE_RATE, frameRate);format.setInteger(MediaFormat.KEY_REPEAT_PREVIOUS_FRAME_AFTER, 1000000 / frameRate);/*MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);format.setInteger(MediaFormat.KEY_COLOR_FORMAT,MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);format.setInteger(MediaFormat.KEY_BIT_RATE, 6000000);format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);*/try {mEncorder = MediaCodec.createEncoderByType(MIME_TYPE);mEncorder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);mInputSurface = mEncorder.createInputSurface();mEncorder.start();} catch (IOException e) {e.printStackTrace();releaseEncorders();}}

将format传给mEncorder,然后调用start,编码器就开始工作了,会自动将数据写入到MediaCodec的缓冲区内,我们拿出缓冲区内编码好的数据,使用MediaMuxer进行混合输出就ok了,看到有大神将,声音和视频的混合之后一起输出,就实现了录屏和录音同步。这个后面可以尝试下的

接着看

private void startRecording() {File saveFile = new File(savePath, System.currentTimeMillis() + ".mp4");try {mMuxer = new MediaMuxer(saveFile.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);Log.e("TAG", "mwidth " + mWidth + " heigh "  + mHeight + "  mdensty " + mDensty + "   Flag "+ DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC + "  surface " + String.valueOf(mInputSurface == null));mediaProjection.createVirtualDisplay("SCREENRECORDER", mWidth, mHeight, mDensty, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,mInputSurface, null, null);drainEncoder();} catch (Exception e) {e.printStackTrace();}finally {releaseEncorders();}}

MediaMuxer需要一个文件来保存输出的视频,并传入一个输出格式
MediaMuxer输出格式目前只支持MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4
MUXER_OUTPUT_WEBM两种。

创建虚拟屏幕之后
就开始编码输出了,

private void drainEncoder() {while (!mQuit.get()) {Log.e("TAG", "drain.....");int bufferIndex = mEncorder.dequeueOutputBuffer(mBufferInfo, 0);if (bufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}}if (bufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {mTrackIndex = mMuxer.addTrack(mEncorder.getOutputFormat());if (!mMuxerStarted && mTrackIndex >= 0) {mMuxer.start();mMuxerStarted = true;}}if (bufferIndex >= 0) {Log.e("TAG", "drain...write..");ByteBuffer bufferData = mEncorder.getOutputBuffer(bufferIndex);if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {mBufferInfo.size = 0;}if (mBufferInfo.size != 0) {if (mMuxerStarted) {bufferData.position(mBufferInfo.offset);bufferData.limit(mBufferInfo.offset + mBufferInfo.size);mMuxer.writeSampleData(mTrackIndex, bufferData, mBufferInfo);}}mEncorder.releaseOutputBuffer(bufferIndex, false);if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {break;}}}}

这段代码呢先拿到输出buffer的index
index的含义:
MediaCodec.INFO_TRY_AGAIN_LATER 超时
MediaCodec.INFO_OUTPUT_FORMAT_CHANGED 格式改变
我们在MediaCodec.INFO_OUTPUT_FORMAT_CHANGED 这个的时候会开启muxer

if (bufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {mTrackIndex = mMuxer.addTrack(mEncorder.getOutputFormat());if (!mMuxerStarted && mTrackIndex >= 0) {mMuxer.start();mMuxerStarted = true;}}

也比较容易理解
之前是muxer并没有调用start(),所以这个时候是没有输出的,混合也是不能起任何作用的

MediaCodec.BUFFER_FLAG_END_OF_STREAM 输出结尾
MediaCodec.BUFFER_FLAG_CODEC_CONFIG 开始编码 我们需要忽略

index大于0,写数据

if (mBufferInfo.size != 0) {if (mMuxerStarted) {bufferData.position(mBufferInfo.offset);bufferData.limit(mBufferInfo.offset + mBufferInfo.size);mMuxer.writeSampleData(mTrackIndex, bufferData, mBufferInfo);}}

不要忘了释放资源,这个是真消耗资源
我用的三星s6 9200,开始没有处理资源,手机卡死好几次,电量也耗得。。。。
代码就不贴了
好了,就到这里

Android5.0录屏相关推荐

  1. Android5.0录屏方案

    导语 本文主要是围绕android直播助手的功能做了一些研究,因为之前对Android多媒体相关的内容知之甚少,只有概念,于是查阅了相关资料并做以总结. 由于我对音视频相关知识零基础所以补充了一些相关 ...

  2. android 5.0 录屏代码,Android5.0录屏

    Android L新增了MediaProjection录屏的api,捣鼓了大半天,照着github上的demo撸了一遍代码,梳理梳理. 录屏实现依赖MediaProjectionManager 经过 ...

  3. android 8.0 录屏命令,Android前置摄像头录制的视频介于7.5和8.0之间 – setVideoFrameRate不起作用 – 三星Galaxy S2...

    我正在尝试使用前置摄像头录制视频,以下是代码段,我将setVideoFrameRate设置为29,但是录制的视频的fps为7.5到8.我需要录制vidio的视频fps 29. recorder.set ...

  4. oCam_v520.0 录屏软件 资源下载

    有道云笔记http://note.youdao.com/noteshare?id=6379b8ddf60323479b68cc0d6e4e5c0a&sub=FB538535BAA9493397 ...

  5. android 录屏方案 VFR和CFR

    android 5.0录屏的例子网上满天飞,我这里主要是总结一下,如何以VFR和CFR的方式来录屏.写这篇文章主要是因为我在做这个功能的过程中,在网上找了很久也没有找到一个固定帧率录屏的例子,后面还是 ...

  6. Fundebug录屏插件更新至0.4.0,修复BUG,优化性能

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: 录屏功能更加强大,欢迎免费试用! 关于Fundebug录屏功能 Fundebug是专业的程序BUG监控服务,当线上应用 ...

  7. 压缩过的js代码怎么还原_Fundebug 前端 JS插件更新至 1.7.0,拆分录屏代码,还原部分 Script error....

    摘要: BUG 监控插件压缩至 18K. 1.7.0拆分了录屏代码,BUG 监控插件压缩至18K,另外我们还原了部分 Script error,帮助用户更方便地 Debug.请大家及时更新哈~ 拆分录 ...

  8. jquery 录屏_Fundebug录屏插件更新至0.6.0

    摘要: 录屏插件的性能进一步优化,传输的数据体积大幅度减少. 录屏功能介绍 Fundebug提供专业的异常监控服务,当线上应用出现 BUG 的时候,我们可以第一时间报警,帮助开发者及时发现 BUG,提 ...

  9. iOS 12.0+系统录屏(一)

    iOS在录屏功能是走过了长长的一段路,在其他平台尤其是直播平台日益火爆的推动下,iOS12.0终于开放在应用中唤起系统录屏权限给开发者.以下内容以iOS 12.0+为基础,不再讨论之前的版本. 理论准 ...

最新文章

  1. 深入剖析MobileNet和它的变种
  2. 如果宁静是 Oracle,万茜、张雨绮、黄圣依是什么?
  3. qt widget 窗口拉伸_QTDesigner的QVBoxLayout自动随窗口拉伸
  4. Day 23:使用 TimelineJS 构建精美的时间轴
  5. linux配置静态ip
  6. Android线程优先级设置方法技巧
  7. Linux学习-07-vim编辑器
  8. python安装教程(Windows最新)
  9. python的itertools库_Python标准库itertools模块使用方法
  10. 分享一款好看的城市选择器
  11. JAVA教程下载-JAVA学习视频教程网盘分享
  12. 湖北省武汉市谷歌高清卫星地图下载
  13. 办公软件excel表格_软件和Excel表格管理仓库的区别?
  14. 何凯明最新一作MAE解读系列1
  15. GPU编程与CG语言之阳春白雪下里巴人.pdf 分享
  16. adobe air linux centos,Adobe AIR(跨平台应用)
  17. 游戏防封技术是学易语言还是学c,易语言写游戏脚本防封执行sqlplus 之后没执行...
  18. Range fro mac(随机数字生成软件)
  19. GNS与WireShark安装流程
  20. 重新认识 Java 的 System.in

热门文章

  1. 机器学习基础——香农熵、相对熵(KL散度)与交叉熵
  2. 评职称自费出书需要多长时间
  3. 人口只有北京的1/3,这个国家创立了全球一半的科技公司
  4. ccflow 代码分析
  5. Codeforces 558C Amr and Chemistry 暴力 - -
  6. Vue+element 实现英雄榜功能
  7. 关键词生成器在线-在线免费关键词生成器
  8. strcat函数 strncat函数
  9. 不要再使用TCHAR和_T了
  10. 【BLE】CC2541之SBL