MediaProjection与MediaRecorder实现录屏
来源:互联网 发布:网络电影投资公司 编辑:程序博客网 时间:2024/06/09 13:31
纸上得来终觉浅,绝知此事要躬行,Android在5.0提供了MediaProjection来实现录屏,但是一直都没有尝试过,这里尝试了一下该方式进行录屏。
其实Demo已经写好很久了,但是始终有一个问题,在某些机型上会偏色,因此这里写出来看看是否有人遇到同样的问题,且希望告知解决方案。
录制
这里界面上有两个按钮,一个控制录制与暂停,另外一个是播放按钮,既然是录制,当然录制完成我们需要看看录制的效果。
布局界面如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.demo.example.activity.ScreenRecordActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="horizontal"> <Button android:id="@+id/record" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="start"/> <Button android:id="@+id/play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="play"/> </LinearLayout> <Chronometer android:id="@+id/update" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal"/> <TextureView android:id="@+id/texture" android:layout_width="match_parent" android:layout_height="match_parent"/></LinearLayout>
两个按钮,一个播放一个停止
Chronometer在界面上改变数字,便于区分视频是否在在录制
TextureView播放界面
回到Activity,我们这里先初始化一下默认信息
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)private void init() { metrics = this.getResources().getDisplayMetrics(); width = 720; height = 1280; //printInfo(); manager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);}
这里宽高就默认为720*1280,也就是视频尺寸
获取了MediaProjectionManager,后面需要他来获得MediaProjection
上面的准备工作就做完了,这里我们将处理逻辑都放到点击事件上,这里我们点击recoder按钮:
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)private void onRecord() { if (isRecording) { stopRecord(); } else { startRecord(); } isRecording = !isRecording; record.setText(isRecording ? "stop" : "start");}@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)private void startRecord() { if (mediaProjection != null) {// 说明已经请求过权限了 onStartRecord(); } else { Intent captureIntent = manager.createScreenCaptureIntent(); startActivityForResult(captureIntent, REQUEST_CODE); }}private void stopRecord() { if (recorder != null) { recorder.stop(); recorder.reset(); }}
点击后执行onRecord,这里做了区分如果是录制,下一次点击则暂停,第一次会执行startRecord.
这里我们来主要看看startRecord,这里我们首先判断mediaProjection是否为空,不为空开始录制,为空我们打开了一个Intent,这是因为录屏是需要权限的。打开对应的页面获得权限。那这里第一次会走到onActivityResult,在onActivityResult中我们主要获取了MediaProjection,如果为空则说明失败了,不为空会进入onStartRecord函数。
onStartRecord主要干了三件事,第一初始化MediaRecorder,第二创建VirtualDisplay
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)private void onStartRecord() { initMediaRecorder(); createVirtualDisplay(); recorder.start(); chronometer.start();}
我们来看看初始化MediaRecorder:
private void initMediaRecorder() { if (recorder == null) { recorder = new MediaRecorder(); recorder.setAudioSource(MediaRecorder.AudioSource.MIC); recorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); recorder.setVideoSize(width, height); recorder.setVideoEncodingBitRate(4 * width * height); recorder.setVideoFrameRate(30); } else { recorder.reset(); } recorder.setOutputFile(getFilePath()); prepare();}private void prepare() { try { recorder.prepare(); } catch (IOException e) { e.printStackTrace(); releaseRecorder(); }}private String getFilePath() { Date date = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHss"); String time = dateFormat.format(date); String absolutePath = getExternalCacheDir().getAbsolutePath(); StringBuilder sb = new StringBuilder(); sb.append(absolutePath).append("/cap/").append(time).append(".3gp"); fileName = sb.toString(); File file = new File(fileName); File parentFile = file.getParentFile(); if (!parentFile.exists()) { parentFile.mkdir(); } return fileName;}
上面主要构造了一个MediaRecorder实例,设置了音频,视频,输出格式,编码格式,视频尺寸,码率,帧率,最后设置了视频输出路径
Note:上面设置的参数有先后顺序,一定不能乱序
最后调用了prepare,所有的参数都在prepares之前
我们来继续看看createVirtualDisplay:
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)private void createVirtualDisplay() { virtualDisplay = mediaProjection.createVirtualDisplay("ScreenRecordActivity", width, height, metrics .densityDpi, VIRTUAL_DISPLAY_FLAGS, recorder.getSurface(), null, null);}
这里我们创建了一个VirtualDisplay,设置了宽,高,密度
设置了recorder.getSurface()将两个联系在一起
上面的最后一步就是调用了MediaRecorder的start函数,进行录制。
其他的一些函数都是清场函数,释放占用的资源
播放
上面已经进行了录制。那这里我们需要进行播放,播放我们采用MediaPlay,MediaPlay大家有用的很多了,这里就大致讲述一下:
private void initMediaPlay() { if (mediaPlayer == null) { mediaPlayer = new MediaPlayer(); } else { mediaPlayer.stop(); mediaPlayer.reset(); mediaPlayer.release(); } try { mediaPlayer.setDataSource(fileName); mediaPlayer.setSurface(surface); mediaPlayer.prepare(); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mediaPlayer.start(); } }); } catch (IOException e) { e.printStackTrace(); }}
设置了视频流的路径
这里主要看看setSurface(surface)函数,这里我们设置了一个surface,这里的surface就是之前TextureView构造出来的surface,将视频流与TextureView联系起来。
那这里的surface是什么构造出来的,我们对TextureView设置了SurfaceTextureListener,在回调中构造surface:
@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { surface = new Surface(surfaceTexture);}
问题
目前上面的录制在大部分手机上是没有问题的,但是在Vivo上会偏色,偏色成粉色,我调整了所有参赛,都没有改变改情况。如果有人有解决方案希望告知。
代码
最后附上源码Code
- MediaProjection与MediaRecorder实现录屏
- Android MediaProjection 录屏
- Android MediaProjection 录屏
- MediaProjection实现截图,与MediaMuxer实现录屏为MP4,Gif格式
- 使用MediaProjection和MediaRecorder实现屏幕录制
- 使用MediaProjection和MediaRecorder实现屏幕录制
- Android MediaProjection截屏与录屏(surfaceview截图)
- Android Multimedia实战(四)MediaProjection实现截图,与MediaMuxer实现录屏为MP4,Gif格式
- Android MediaProjection截屏与录屏(ScreenCapture Library 的使用)(二)
- Android实现录屏直播(三)MediaProjection + VirtualDisplay + librtmp + MediaCodec实现视频编码并推流到rtmp服务器
- Android5.0以上使用MediaProjection截图和录屏
- Android5.0以上使用MediaProjection截图和录屏
- android -- MediaRecorder 自定义视频录
- Android Multimedia框架总结(二十五)MediaProjection实现手机截屏(无须root)
- 【Android】MediaRecorder/MediaPlayer实现录音与播放录音
- MediaRecorder与MediaPlayer步骤
- Android MediaRecorder与AudioRecorder
- 录音(MediaRecorder)与播放
- 面向对象语言三大特性
- CSDN博客开通手记
- 2017-10-30
- android中AIDL机制分析
- base64
- MediaProjection与MediaRecorder实现录屏
- 常用WKID
- 《赢》读书摘要02
- Git warning:LF will be replaced by CRLF in readme.txt的原因与解决方案
- Android分享视频链接到VK无法打开
- Mysql中的视图
- Spring框架之注册—AliasRegistry接口
- JavaScript 开发者的 10 款必备工具
- SAP Business One (SAP软件)会计师事务所行业ERP成功故事-东审鼎立国际会计师事务所