问题

在android中有时候我们需要对屏幕进行截屏操作,单一的截屏操作好解决可以通过activity的顶层view DecorView获取一个bitmap,得到就是当前activity上面的全部视图。

 View view = activity.getWindow().getDecorView();view.setDrawingCacheEnabled(true);view.buildDrawingCache();Bitmap bmp = view.getDrawingCache();DisplayMetrics dm = new DisplayMetrics();activity.getWindowManager().getDefaultDisplay().getMetrics(dm);Bitmap ret = Bitmap.createBitmap(bmp, 0, 0, dm.widthPixels, dm.heightPixels);view.destroyDrawingCache();

如果activity中包含一些视频播放器比如SurfaceView GLSurfaceView
TextureView,在调用截屏代码会发现播放视频的部分是黑屏的,原因是这几种视频渲染的view通过以上代码拿到的是缓冲区不是真正的图像。

解决办法

android5.0以上系统提供了一个 MediaProjectionManager
类来对手机进行录屏操作,也支持获取手机的Image图像的操作,知道了这些我们就可以通过提供的api来进行截屏操作了。

这里通过Service来操作截屏和录屏的api

1.绑定截屏的Service

 Intent intent = new Intent(this, ScreenService.class);bindService(intent, mServiceConnection, BIND_AUTO_CREATE);public void onServiceConnected(ComponentName className, IBinder service) {DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);ScreenService.RecordBinder binder = (ScreenService.RecordBinder) service;recordService = binder.getRecordService();recordService.setConfig(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi);mButton.setEnabled(true);mButton.setText(recordService.isRunning() ? "结束" : "开始");}

2.请求权限 onActivityResult 方法中回调。

 Intent captureIntent = projectionManager.createScreenCaptureIntent();startActivityForResult(captureIntent, RECORD_REQUEST_CODE);
  成功后@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {//######## 截屏逻辑 ########mediaProjection = projectionManager.getMediaProjection(resultCode, data);recordService.setMediaProject(mediaProjection);recordService.initImageReader();}}

3. 获取截屏

  @Overridepublic void onClick(View view) {//########  截屏逻辑 ########Bitmap bitmap = recordService.getBitmap();mImageView.setImageBitmap(bitmap);}

录屏

录屏需要初始化一些录屏参数,输入麦克风类型视频类型,保存路径等

 private void initRecorder() {mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);mediaRecorder.setOutputFile(getSavePath() + System.currentTimeMillis() + ".mp4");mediaRecorder.setVideoSize(width, height);mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);mediaRecorder.setVideoFrameRate(30);try {mediaRecorder.prepare();} catch (IOException e) {e.printStackTrace();}}

开始录屏

  mediaRecorder.start();

保存路径

完整Service代码

public class ScreenService extends Service {
private MediaRecorder mediaRecorder;
private VirtualDisplay virtualDisplay;
private boolean running;
private int width = 720;
private int height = 1080;
private int dpi;
private ImageReader mImageReader;
private MediaProjection mediaProjection;

 @Overridepublic IBinder onBind(Intent intent) {return new RecordBinder();}@Overridepublic void onCreate() {super.onCreate();running = false;mediaRecorder = new MediaRecorder();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {super.onDestroy();}public void setMediaProject(MediaProjection project) {mediaProjection = project;}public boolean isRunning() {return running;}public void setConfig(int width, int height, int dpi) {this.width = width;this.height = height;this.dpi = dpi;}/*** 开始录屏** @return true*/public boolean startRecord() {if (mediaProjection == null || running) {return false;}initRecorder();createVirtualDisplay();mediaRecorder.start();running = true;return true;}/*** 结束录屏** @return true*/public boolean stopRecord() {if (!running) {return false;}running = false;mediaRecorder.stop();mediaRecorder.reset();virtualDisplay.release();mediaProjection.stop();return true;}public void setMediaProjection(MediaProjection mediaProjection) {this.mediaProjection = mediaProjection;}/*** 初始化ImageRead参数*/public void initImageReader() {if (mImageReader == null) {int maxImages = 2;mImageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, maxImages);createImageVirtualDisplay();}}/*** 创建一个录屏 Virtual*/private void createVirtualDisplay() {virtualDisplay = mediaProjection.createVirtualDisplay("mediaprojection", width, height, dpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null, null);}/*** 创建一个ImageReader Virtual*/private void createImageVirtualDisplay() {virtualDisplay = mediaProjection.createVirtualDisplay("mediaprojection", width, height, dpi,DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader.getSurface(), null, null);}/*** 初始化保存屏幕录像的参数*/private void initRecorder() {mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);mediaRecorder.setOutputFile(getSavePath() + System.currentTimeMillis() + ".mp4");mediaRecorder.setVideoSize(width, height);mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);mediaRecorder.setVideoFrameRate(30);try {mediaRecorder.prepare();} catch (IOException e) {e.printStackTrace();}}/*** 获取一个保存屏幕录像的路径** @return path*/public String getSavePath() {if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {String rootDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" +"ScreenRecord" + "/";File file = new File(rootDir);if (!file.exists()) {if (!file.mkdirs()) {return null;}}return rootDir;} else {return null;}}/*** 请求完权限后马上获取有可能为null,可以通过判断is null来重复获取。*/public Bitmap getBitmap() {Bitmap bitmap = cutoutFrame();if (bitmap == null) {getBitmap();}return bitmap;}/*** 通过底层来获取下一帧的图像** @return bitmap*/public Bitmap cutoutFrame() {Image image = mImageReader.acquireLatestImage();if (image == null) {return null;}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);return Bitmap.createBitmap(bitmap, 0, 0, width, height);}public class RecordBinder extends Binder {public ScreenService getRecordService() {return ScreenService.this;}}

demo下载

github

作者:金威JW
链接:http://www.jianshu.com/p/2a330e3cfdac
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

android视频截屏手机录屏实现相关推荐

  1. android录屏弹窗,android视频截屏手机录屏实现代码

    本文介绍了android视频截屏&手机录屏实现代码,分享给大家,希望对大家有帮助 问题 在android中有时候我们需要对屏幕进行截屏操作,单一的截屏操作好解决可以通过activity的顶层v ...

  2. 华为手机怎么录屏?分享2个好用的手机录屏方法!

    案例:华为手机怎么录制屏幕? [有些内容通过文字和图片,不能很好地表达.我想把内容录制下来,发给别人,方便他们理解.有人知道华为手机怎么录屏吗?] 华为是一款知名的智能手机品牌,其强大的性能和丰富的功 ...

  3. android 实现手机录屏功能,基于MediaProjection实现Android移动手机截屏和录屏功能

    Android软件应用经常要求实现截屏和录屏的功能,那么如何实现Android软件截屏和录屏功能呢?本文将介绍基于MediaProjection实现Android移动手机截屏和录屏功能. MediaP ...

  4. Android 音视频开发(六) -- Android Mediaprojection 截屏和录屏

    Android 音视频开发(一) – 使用AudioRecord 录制PCM(录音):AudioTrack播放音频 Android 音视频开发(二) – Camera1 实现预览.拍照功能 Andro ...

  5. Android截屏、录屏,适配AndroidQ以上

    使用MediaProjectionManager,VirtualDisplay,AudioRecord,MediaCodec以及MediaMuxer等API实现屏幕录制功能.MediaProjecti ...

  6. Android手机录屏并制作Gif

    做效果展示时经常需要一些Gif图来显示动态效果,我目前使用的方法是手机录屏生成视频文件,再通过第三方软件用视频文件生成动图.刚才制作了一个动图效果图如下: 这里我使用的是adb的screenrecor ...

  7. android 自定义录像机,android 手机录屏,最简单的 3 种方法

    原标题:android 手机录屏,最简单的 3 种方法 公众号文章不支持插入外链,下面提到的所有工具,都可点击 阅读原文前往我的个人网站 kejiweixun.com 下载. 安卓手机录制屏幕有很多方 ...

  8. android 手机录屏功能,手机自带录屏功能在哪里找?轻松搞定屏幕录制

    手机的录屏功能如何使用?智能手机发展到现在,除了无线通话功能.讯息发送功能之外,又逐渐发展出拍照功能.上网功能.各类应用交互功能.尤其近几年在手机上看视频成为打发碎片化时间的重要消遣,在手机上录屏的需 ...

  9. Android 关于禁止应用截屏和录屏

    APP有时候为了保护用户的隐私安全会禁止用户录屏和截屏,录入说视频交友类的app,金融类的app等 可以在app的onCreate方法中添加这么一段代码: @Overrideprotected voi ...

最新文章

  1. Spread for Windows Forms高级主题(7)---自定义打印的外观
  2. 数学建模学习笔记——灰色关联分析(评价类)
  3. Python——基于OpenCV获取倾斜子图的一种方法
  4. 《C# 程序员的自我修养》送书活动结果公布
  5. mac下nvm_Mac OS 使用 nvm 管理 node 与 npm 版本
  6. NumPy 1.19.3 发布,Python 科学计算包
  7. bash功能特性二 命令别名和历史命令
  8. 电脑画图和计算机不见了,电脑中自带的Window画图工具不见了如何恢复
  9. 【Python机器学习】决策树ID3算法结果可视化附源代码 对UCI数据集Caesarian Section进行分类
  10. 【数学建模】python建模专用数据清洗代码(本人实践)
  11. 实战攻防比赛中作为防守方需要做哪些工作
  12. 从零开始的硬改路由器记录
  13. GoldWave教程分享:删除声道该怎么操作?
  14. 关于奥威亚自动录播系统的设置使用小笔记
  15. python暴力解压rar压缩包
  16. 上海交通大学计算机科学与技术招生网,上海交通大学计算机科学与技术研究生招生...
  17. 培训班和科班出来的程序员有什么不同之处?看完这个你就能明白!
  18. 慕课-工程伦理第十二讲参考答案
  19. PS基础及选框工具笔记(CS6)
  20. android开发实名认证弹窗,fusionAAS-android-demo

热门文章

  1. (c语言)使用函数验证哥德巴赫猜想
  2. 挪威的森林--第二章 好友之死
  3. 【入门】游戏运营不完全手册
  4. MyBatis(多表查询,动态SQL的使用)
  5. 小体积掌上读数仪( MFang)掌上宝便携式振弦读数仪
  6. 全球最新超级计算机排行前十…
  7. 最简单的AR开发入门教程(一)
  8. 002 Latex引用包显示“File `article.cls‘ not found的问题
  9. apk反编译重新打包时遇到小问题
  10. 2.5亿!华为成立新公司