android视频截屏手机录屏实现
问题
在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视频截屏手机录屏实现相关推荐
- android录屏弹窗,android视频截屏手机录屏实现代码
本文介绍了android视频截屏&手机录屏实现代码,分享给大家,希望对大家有帮助 问题 在android中有时候我们需要对屏幕进行截屏操作,单一的截屏操作好解决可以通过activity的顶层v ...
- 华为手机怎么录屏?分享2个好用的手机录屏方法!
案例:华为手机怎么录制屏幕? [有些内容通过文字和图片,不能很好地表达.我想把内容录制下来,发给别人,方便他们理解.有人知道华为手机怎么录屏吗?] 华为是一款知名的智能手机品牌,其强大的性能和丰富的功 ...
- android 实现手机录屏功能,基于MediaProjection实现Android移动手机截屏和录屏功能
Android软件应用经常要求实现截屏和录屏的功能,那么如何实现Android软件截屏和录屏功能呢?本文将介绍基于MediaProjection实现Android移动手机截屏和录屏功能. MediaP ...
- Android 音视频开发(六) -- Android Mediaprojection 截屏和录屏
Android 音视频开发(一) – 使用AudioRecord 录制PCM(录音):AudioTrack播放音频 Android 音视频开发(二) – Camera1 实现预览.拍照功能 Andro ...
- Android截屏、录屏,适配AndroidQ以上
使用MediaProjectionManager,VirtualDisplay,AudioRecord,MediaCodec以及MediaMuxer等API实现屏幕录制功能.MediaProjecti ...
- Android手机录屏并制作Gif
做效果展示时经常需要一些Gif图来显示动态效果,我目前使用的方法是手机录屏生成视频文件,再通过第三方软件用视频文件生成动图.刚才制作了一个动图效果图如下: 这里我使用的是adb的screenrecor ...
- android 自定义录像机,android 手机录屏,最简单的 3 种方法
原标题:android 手机录屏,最简单的 3 种方法 公众号文章不支持插入外链,下面提到的所有工具,都可点击 阅读原文前往我的个人网站 kejiweixun.com 下载. 安卓手机录制屏幕有很多方 ...
- android 手机录屏功能,手机自带录屏功能在哪里找?轻松搞定屏幕录制
手机的录屏功能如何使用?智能手机发展到现在,除了无线通话功能.讯息发送功能之外,又逐渐发展出拍照功能.上网功能.各类应用交互功能.尤其近几年在手机上看视频成为打发碎片化时间的重要消遣,在手机上录屏的需 ...
- Android 关于禁止应用截屏和录屏
APP有时候为了保护用户的隐私安全会禁止用户录屏和截屏,录入说视频交友类的app,金融类的app等 可以在app的onCreate方法中添加这么一段代码: @Overrideprotected voi ...
最新文章
- Spread for Windows Forms高级主题(7)---自定义打印的外观
- 数学建模学习笔记——灰色关联分析(评价类)
- Python——基于OpenCV获取倾斜子图的一种方法
- 《C# 程序员的自我修养》送书活动结果公布
- mac下nvm_Mac OS 使用 nvm 管理 node 与 npm 版本
- NumPy 1.19.3 发布,Python 科学计算包
- bash功能特性二 命令别名和历史命令
- 电脑画图和计算机不见了,电脑中自带的Window画图工具不见了如何恢复
- 【Python机器学习】决策树ID3算法结果可视化附源代码 对UCI数据集Caesarian Section进行分类
- 【数学建模】python建模专用数据清洗代码(本人实践)
- 实战攻防比赛中作为防守方需要做哪些工作
- 从零开始的硬改路由器记录
- GoldWave教程分享:删除声道该怎么操作?
- 关于奥威亚自动录播系统的设置使用小笔记
- python暴力解压rar压缩包
- 上海交通大学计算机科学与技术招生网,上海交通大学计算机科学与技术研究生招生...
- 培训班和科班出来的程序员有什么不同之处?看完这个你就能明白!
- 慕课-工程伦理第十二讲参考答案
- PS基础及选框工具笔记(CS6)
- android开发实名认证弹窗,fusionAAS-android-demo