不积跬步,无以至千里;不积小流,无以成江海。要沉下心来,诗和远方的路费真的很贵!
Android录屏功能实现—MediaProjection
参考博客:Android实现录屏MediaProjection以及相关异常解决
参考GitHub:github中最容易理解的Android录屏的版本
概述
Android录屏功能实现有很多种方式,这里记录最常见的一种,用Android自带的apk来实现,即使用MediaProjection来实现。
工具类
实现Android的录屏功能,需要用到一些工具类:MediaProjection,MediaProjectionManager,MediaRecoder,VirtualDisplay,DisplayMetrics等。
作用
MediaProjection
用于屏幕采集。
MediaProjectionManager
用于创建MediaProjection。
MediaRecoder
用于屏幕录制。
VirtualDisplay
用于创建虚拟屏幕。
DisplayMetrics
用于获取屏幕参数。
过程
权限申请
需要使用录屏功能,必须请求读写和录像录音权限。
- 静态权限申请——
Manifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.RECORD_AUDIO"/>
Android 6.0以上还需要动态申请权限
//权限检查,连接录屏服务
public void checkPermission() {
//调用检查权限接口进行权限检查
if ((ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) && (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)){
//如果没有权限,获取权限
//调用请求权限接口进行权限申请
ActivityCompat.requestPermissions(this,new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.RECORD_AUDIO},PERMISSION_REQUEST_CODE);
}else{
//有权限,连接录屏服务,进行录屏
connectService();
}
}
- 申请权限后,还需要判断用户是否同意
//没有权限,去请求权限后,需要判断是否请求成功
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == PERMISSION_REQUEST_CODE){
//请求码相同
if(grantResults.length != 0 &&
((grantResults[0] != PackageManager.PERMISSION_GRANTED) ||
(grantResults[1] != PackageManager.PERMISSION_GRANTED))){
//如果结果都存在,但是至少一个没请求成功,弹出提示
Toast.makeText(MainActivity.this,"请同意必须的应用权限,否则无法正常使用该功能!", Toast.LENGTH_SHORT).show();
}else if(grantResults.length != 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED &&
grantResults[1] == PackageManager.PERMISSION_GRANTED){
//如果结果都存在,两个权限都申请成功,连接服务,启动录屏
connectService();
}
}
}
连接服务
注意点:记住一定要在Manifest中声明自定义的Service,不然后面得到的Service对象都是NULL。
Manifest.xml
<service android:name=".ScreenRecordService"/>
- 连接服务
//连接服务
public void connectService(){
//通过intent为中介绑定Service,会自动create
Intent intent = new Intent(this,ScreenRecordService.class);
//绑定过程连接,选择绑定模式
bindService(intent,serviceConnection,BIND_AUTO_CREATE);
}
- 判断服务是否连接成功
- 成功则向系统发送录屏请求
//连接服务成功与否,具体连接过程
//调用连接接口,实现连接,回调连接结果
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//服务连接成功,需要通过Binder获取服务,达到Activity和Service通信的目的
//获取Binder
ScreenRecordService.ScreenRecordBinder binder = (ScreenRecordService.ScreenRecordBinder) iBinder;
//通过Binder获取Service
screenRecordService = binder.getScreenRecordService();
//获取到服务,初始化录屏管理者
mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
//通过管理者,创建录屏请求,通过Intent
Intent captureIntent = mediaProjectionManager.createScreenCaptureIntent();
//将请求码作为标识一起发送,调用该接口,需有返回方法
startActivityForResult(captureIntent,REQUEST_CODE);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
//连接失败
Toast.makeText(MainActivity.this,"录屏服务未连接成功,请重试!",Toast.LENGTH_SHORT).show();
}
};
- 请求之后,获得返回的信息
@Override
//返回方法,获取返回的信息
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//首先判断请求码是否一致,结果是否ok
if(requestCode == REQUEST_CODE && resultCode == RESULT_OK){
//录屏请求成功,使用工具MediaProjection录屏
//从发送获得的数据和结果中获取该工具
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode,data);
//将该工具给Service,并一起传过去需要录制的屏幕范围的参数
if(screenRecordService != null){
screenRecordService.setMediaProjection(mediaProjection);
screenRecordService.setConfig(metrics.widthPixels,metrics.heightPixels,metrics.densityDpi);
}
}
}
开始录制
- 获得了返回的信息,将参数都发送过去后,开始录制
//服务的两个主要逻辑
//开始录屏
public boolean startRecord() {
//首先判断是否有录屏工具以及是否在录屏
if (mediaProjection == null || running) {
return false;
}
//有录屏工具,没有在录屏,就进行录屏
//初始化录像机,录音机Recorder
initRecorder();
//根据获取的屏幕参数创建虚拟的录屏屏幕
createVirtualDisplay();
//本来不加异常也可以,但是这样就不知道是否start成功
//万一start没有成功,但是running置为true了,就产生了错误也无提示
//提示开始录屏了,但是并没有工作
try{
//准备工作都完成了,可以开始录屏了
mediaRecorder.start();
//标志位改为正在录屏
running = true;
return true;
}catch (Exception e){
e.printStackTrace();
//有异常,start出错,没有开始录屏,弹出提示
Toast.makeText(this,

本文详细介绍了如何使用MediaProjection实现Android系统的录屏功能,包括权限申请、服务连接、开始和停止录制的步骤,以及涉及到的关键工具类如MediaProjection、MediaRecorder、VirtualDisplay等的使用方法。
最低0.47元/天 解锁文章
1078

被折叠的 条评论
为什么被折叠?



