预备知识
Android MediaProjection学习(一)之实现屏幕截图 通过预备知识我们应该知道MediaProjection的相关方法和知识。在屏幕截图里我们用了ImageReader来获取截图,而在这一节中我们通过另外一个工具MediaRecorder来获取屏幕的视频。
MediaRecorder
Google官方文档:官方文档
Used to record audio and video. The recording control is based on a simple state machine (see below).A common case of using MediaRecorder to record audio works as follows:
MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(PATH_NAME);
recorder.prepare();
recorder.start(); // Recording is now started
...
recorder.stop();
recorder.reset(); // You can reuse the object by going back to setAudioSource() step
recorder.release(); // Now the object cannot be reused
引用结束
其实我们结合流程图来看就可以明白了,首先我们要初始化Recorder,调用相关方法。然后顺着流程图走,然后就是数据源的配置,方法如图。配置完这些后我们就调用prepare()方法来让Recorder处于预备状态,最后调用start()就开始录制了。
屏幕录制
了解了上述知识以后我们就可以开始屏幕录制了,现在只剩一个问题,那就是MediaRecorder的视频源从哪来?我们先看看几个常见的视频源。
Constants
类型 | 名称 | 解释 |
int | CAMERA | Camera video source,Using the Camera API as video source. |
int | DEFAULT | |
int | SURFACE | Surface video source,Using a Surface as video source. |
第一个CAMERA视频源来自系统相机的API,第三个SURFACE则是通过surface来获取视频。是不是有头绪了,没错我们的截屏就是通过ImageReader的getSurface方法获取了surface然后转换后就可以了。录屏也是一样,通过MediaRecorder的getSurface方法来获取一个surface来录屏就可以了。
这里需要注意的一点就是,我们需要把我们的录屏放在服务里运行,就可以录制我们程序以外的屏幕内容了。
代码
首先我们需要获取一个MediaProjection方法如下:
private MediaProjection createMediaProjection() {
Log.i(TAG, "Create MediaProjection");
return ((MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE)).getMediaProjection(mResultCode, mResultData);
}
然后初始化MediaRecorder:
private MediaRecorder createMediaRecorder() {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
Date curDate = new Date(System.currentTimeMillis());
String curTime = formatter.format(curDate).replace(" ", "");
String videoQuality = "HD";
if(isVideoSd) videoQuality = "SD";
Log.i(TAG, "Create MediaRecorder");
MediaRecorder mediaRecorder = new MediaRecorder();
if(isAudio) mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setOutputFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + "/" + videoQuality + curTime + ".mp4");
mediaRecorder.setVideoSize(mScreenWidth, mScreenHeight); //after setVideoSource(), setOutFormat()
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); //after setOutputFormat()
if(isAudio) mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); //after setOutputFormat()
int bitRate;
if(isVideoSd) {
mediaRecorder.setVideoEncodingBitRate(mScreenWidth * mScreenHeight);
mediaRecorder.setVideoFrameRate(30);
bitRate = mScreenWidth * mScreenHeight / 1000;
} else {
mediaRecorder.setVideoEncodingBitRate(5 * mScreenWidth * mScreenHeight);
mediaRecorder.setVideoFrameRate(60); //after setVideoSource(), setOutFormat()
bitRate = 5 * mScreenWidth * mScreenHeight / 1000;
}
try {
mediaRecorder.prepare();
} catch (IllegalStateException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.i(TAG, "Audio: " + isAudio + ", SD video: " + isVideoSd + ", BitRate: " + bitRate + "kbps");
return mediaRecorder;
}
这段代码包含了录制高清和普清视频,帧率设置,视频源,文件输出路径等。
最后我们调用MediaProjection的createVirtualDisplay方法:
private VirtualDisplay createVirtualDisplay() {
Log.i(TAG, "Create VirtualDisplay");
return mMediaProjection.createVirtualDisplay(TAG, mScreenWidth, mScreenHeight, mScreenDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mMediaRecorder.getSurface(), null, null);
}
这里通过mMediaRecorder.getSurface()将屏幕内容给我们初始化的MediaRecorder,最后调用MediaRecorder的start()就可以将录制的视频输出到我们指定的目录下了。
Summary总结
我们捋一下录屏的步骤。
Ⅰ 获取MediaProjectionManager和MediaProjection
Ⅱ 初始化MediaRecorder
Ⅲ 调用MediaProjection的createVirtualDisplay方法传入MediaRecorder的getSurface方法返回的surface
Ⅳ 调用MediaRecorder的start()方法
然后就可以实现录屏功能了,开心๑乛◡乛๑。