博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 5.0+ 屏幕录制实现
阅读量:7187 次
发布时间:2019-06-29

本文共 4784 字,大约阅读时间需要 15 分钟。

前言

Android 从 4.0 开始就提供了手机录屏方法,但是需要 root 权限,比较麻烦不容易实现。但是从 5.0 开始,系统提供给了 app 录制屏幕的一系列方法,不需要 root 权限,只需要用户授权即可录屏,相对来说较为简单。本文是在参考了网络上其他录屏资料后完成的,。以下将介绍开发录屏功能的一系列步骤以及实现过程中所遇到的一些需要注意的事项。

实现步骤

  1. 在清单文件中声明需要的权限

因为录制用到麦克风,所以需要加上 AUDIO 权限,

复制代码

如果开发的 app targetApi 在 6.0 以上时,还需要动态获取权限。

public static void checkPermission(AppCompatActivity activity) {        if (Build.VERSION.SDK_INT >= 23) {            int checkPermission =                    ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO)                            + ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_PHONE_STATE)                            + ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)                            + ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);            if (checkPermission != PackageManager.PERMISSION_GRANTED) {                //动态申请                ActivityCompat.requestPermissions(activity, new String[]{                        Manifest.permission.RECORD_AUDIO,                        Manifest.permission.READ_PHONE_STATE,                        Manifest.permission.READ_EXTERNAL_STORAGE,                        Manifest.permission.WRITE_EXTERNAL_STORAGE}, 123);                return;            } else {                return;            }        }        return;    }    复制代码
  1. 获取用户录制屏幕授权

这里先介绍 MediaProjectionManager , MediaProjectionManager 是系统提供的一种服务,当我们拿到这个服务对象,可以创建一个 Intent ,通过这个 Intent 可以启动一个弹框样式的 Activity,如果用户授权了,那我们便可以继续下一步屏幕录制。需要说明的是,Intent 是去启动另一个 Activity 的,有极少极少的机型是没有对应的授权Activity 的,所以这里需要多加判断,防止应用奔溃。

MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) activity.                            getSystemService(Context.MEDIA_PROJECTION_SERVICE);                    if (mediaProjectionManager != null){                        Intent intent = mediaProjectionManager.createScreenCaptureIntent();                        PackageManager packageManager = activity.getPackageManager();                        if (packageManager.resolveActivity(intent,PackageManager.MATCH_DEFAULT_ONLY) != null){                            //存在录屏授权的Activity                             activity.startActivityForResult(intent,requestCode);                        }else {                            Toast.makeText(activity,R.string.can_not_record_tip,Toast.LENGTH_SHORT).show();                        }                    }复制代码
  1. 在 onActivityResult 对用户的授权做处理

即使用户授权了,同意录制操作,仍然需要捕获异常,因为有可能会出现这样一种情况,就是用户在同意录屏的时候系统也正在录屏,录屏操作冲突了。

@Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK){            try {                ScreenUtil.setUpData(resultCode,data);            } catch (Exception e) {                e.printStackTrace();            }        } else {            ToastUtil.show(this,"拒绝录屏");        }    }复制代码
  1. 初始化 MediaRecorder、创建 VirtualDisplay
@TargetApi(Build.VERSION_CODES.LOLLIPOP)    private void setUpMediaRecorder() {        mRecordFilePath = getSaveDirectory()  + File.separator+  System.currentTimeMillis() + ".mp4";        if (mMediaRecorder == null){            mMediaRecorder = new MediaRecorder();        }        //设置音频来源        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);        //设置视频来源        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);        //输出的录屏文件格式        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);        //录屏文件路径        mMediaRecorder.setOutputFile( mRecordFilePath );        //视频尺寸        mMediaRecorder.setVideoSize(mRecordWidth, mRecordHeight);        //音视频编码器        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);        //比特率        mMediaRecorder.setVideoEncodingBitRate((int) (mRecordWidth * mRecordHeight * 3.6));        //视频帧率        mMediaRecorder.setVideoFrameRate(20);        try {            mMediaRecorder.prepare();        } catch (IOException e) {            e.printStackTrace();        }    }    复制代码

这一步是整个录屏操作最为关键的一步!我们初始化了 MediaRecorder,设置了是否录上声音、录屏文件格式、录屏文件路径、音视频的编码器、比特率、视频帧率等 然后将在步骤 3 中的 resultCode 以及 data 作为必要的参数通过 MediaProjectionManager 创建 VirtualDisplay。VirtualDisplay 可以理解为虚拟的呈现器,它可以捕获屏幕上的内容,并将其捕获的内容渲染到 Surface 上(Surace 由 MediaRecorder 提供,通过 getSurface() 方法得到),MediaRecorder 再进一步将其封装处理为 Mp4 文件。

经过以上步骤 prepare 之后,当再次调用 MediaRecorder.start() 就可以开始录屏了,这里同意也需要注意的时,调用 start() 方法开始录屏之后,不能立即调用 stop()方法停止录屏,否则会奔溃。测试在测试录屏功能时立马停止录屏,应用奔溃,一直找不到原因。直到看到了源码( API 26 )里的注释

所以为了反正奔溃,在 stop 的时候捕获异常,并且置空 MediaRecorder,下次录屏的时候再重新生成 MediaRecorder。

最后

由于知识水平有限,难免有错误遗漏,欢迎指正!项目地址为

转载地址:http://ejfkm.baihongyu.com/

你可能感兴趣的文章
添加非浮动的清楚元素围住浮动元素
查看>>
CentOS挂载NTFS盘符问题
查看>>
文档里组件中的methods方法调用
查看>>
Play 2.0 用户指南 - 异步HTTP编程 --针对Scala开发者
查看>>
Swift 2.0 异常处理
查看>>
Java学习之Xml系列二:xml按条件查询、xml递归遍历所有元素和属性
查看>>
Tomcat7 redis session共享
查看>>
用逻辑运算符实现三目运算符
查看>>
php的openssl_private_encrypt的python实现
查看>>
JDK8新特性(3):Stream API补充介绍
查看>>
php连接状态测试(运行中 关闭浏览器)
查看>>
整合springMVC,Mybatis的Maven项目框架
查看>>
Keras 线性回归
查看>>
Oracle优化查询改写(第二章-给查询结果排序)
查看>>
PHP实现排列组合
查看>>
Fragment的commit的注意事项
查看>>
[UE4]LOG
查看>>
3306 scan script
查看>>
ubuntu下安装 openssl 开发库
查看>>
activemq持久化
查看>>