預備知識
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()方法
然後就可以實現錄屏功能了,開心๑乛◡乛๑。