您的位置:首页 > 移动开发 > Android开发

Android Lollipop (5.0) 屏幕录制实现

2016-07-12 16:48 477 查看

引言

网上很多关于 Android 录屏的解决方案是通过读取
/dev/graphics/fb0
里面的 frame buffer,然后再通过各种开源编码器转为视频,但必须要
root
才行,而且有些手机即便你
root
还是不能成功,获取到的 framebuffer 全是 0, 所以不是一个很好的解决方案。从 Android 4.4 Google 引入了通过
adb
命令录屏的功能,需要通过 USB 调试连接到 PC,运行
adb shell screenrecord /sdcard/xxxx.mp4
开始录屏,并且录屏限制时长最长 3 分钟。Android 5.0 引入
MediaProject
,可以不需要
adb
,也不用
root
就可以录屏,但需要弹权限获取窗口,需要用户允许才行,这里主要介绍 Android 5.0+ 利用
MediaProject
在非
root
情况下实现屏幕录制。转载请注明出处:单刀土豆

基本原理

在 Android 5.0,Google 终于开放了视频录制的接口,其实严格来说,是屏幕采集的接口,也就是
MediaProjection

MediaProjectionManager


具体实现步骤

1 申请权限

在 AndroidManifest 中添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>

Android 6.0 加入的动态权限申请,如果应用的
targetSdkVersion
是 23,申请敏感权限还需要动态申请

if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_REQUEST_CODE);
}
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.RECORD_AUDIO)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.RECORD_AUDIO}, AUDIO_REQUEST_CODE);
}

2 获取 MediaProjectionManager 实例

MediaProjectionManager
也是系统服务的一种,通过
getSystemService
来获取实例

MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);

3 发起屏幕捕捉请求

Intent captureIntent= projectionManager.createScreenCaptureIntent();
startActivityForResult(captureIntent, REQUEST_CODE);

4 获取 MediaProjection

通过
onActivityResult
返回结果获取
MediaProjection


protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {
mediaProjection = projectionManager.getMediaProjection(resultCode, data);
}
}

5 创建虚拟屏幕

这一步就是通过
MediaProject
录制屏幕的关键所在,
VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
参数是指创建屏幕镜像,所以我们实际录制内容的是屏幕镜像,但内容和实际屏幕是一样的,并且这里我们把
VirtualDisplay
的渲染目标 Surface 设置为
MediaRecorder
getSurface
,后面我就可以通过
MediaRecorder
将屏幕内容录制下来,并且存成 video 文件

private void createVirtualDisplay() {
virtualDisplay = mediaProjection.createVirtualDisplay(
"MainScreen",
width,
height,
dpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mediaRecorder.getSurface(),
null, null);
}

6 录制屏幕数据

这里利用
MediaRecord
将屏幕内容保存下来,当然也可以利用其它方式保存屏幕内容,例如:
ImageReader


private void initRecorder() {
File file = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + ".mp4");
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setOutputFile(file.getAbsolutePath());
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();
}
}

public boolean startRecord() {
if (mediaProjection == null || running) {
return false;
}
initRecorder();
createVirtualDisplay();
mediaRecorder.start();
running = true;
return true;
}

源码地址

完整代码地址

文/单刀土豆(简书作者)

原文链接:http://www.jianshu.com/p/e9a9771eb7b8

著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: