Android 5.0+ 屏幕录制实现

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

实现步骤

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

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

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

如果开发的 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。

最后

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

原文地址:https://www.cnblogs.com/zhujiabin/p/9681707.html

时间: 2024-08-30 08:19:16

Android 5.0+ 屏幕录制实现的相关文章

android 实现屏幕录制功能

https://github.com/guaju/ScreenRecordLibrary 本库是基于MediaProjection封装的手机屏幕录制开源库,并提交到Jcenter,方便大家使用 使用方法: module中的build.gradle中的depandencies中添加依赖即可,如下 dependencies { //xxxxxx compile 'com.guaju:screenrecorderlibrary:1.0.1' } 目前最新的版本是1.0.1,仅仅是朋友用了用,如果大家使

oCam Pre v416.0 体积小的屏幕录制工具绿色破解版

鸡哥这两天再考虑要不要垂直发展网站,想象还是算了,本来内容就不太多,再专一一个内容的话更没东西更新了.这不早上闲逛了逛发现了个屏幕录像神器,oCam是款免费屏幕录像利器!这款免费屏幕录制捕捉工具,编码功能强大,支持游戏录像,可录制任何区域,可选全屏模式或自定义区域截图:还可捕捉到正在播放的声音:非常简单易用,而且完全免费.操作步骤只需三步:1.设置屏3幕录制范围:2.点击录制按钮:3.停止录制并保存:即可完成录像!  鸡哥还分享过一个韩国的录屏软件Bandicam破解版,有专门的游戏录制功能,鸡

Android 5.0 Screen pinning 屏幕固定功能

2015.03.13更新 恩 前几天看到android 5.1 出来了,Screen pinning这一部分有改动,具体改了什么还没看到. 这个暂时相对冷门的功能,如果你能看到这篇文章说明你还是有点了解的. 屏幕固定是android 5.0 上的新功能 其Api介绍如下: 我说一点比较重要的吧,就是开了屏幕固定以后,通知栏和状态栏会隐藏,home键和recent键会失效(单独按会失效),然后还不准启动其他activity. 就是说 你只能在这个应用内部干事情.比如你吧手机借给别人的时候就可以用这

Android 7.0 Nougat(牛轧糖)---对开发者来说

android 7.0出来了.让你的app准备迎接最新的android版本吧,支持节省电量和内存,这样新的系统行为.使用多窗口UI.直接恢复通知以及其他操作来扩展你的app. android 7.0介绍了各种各样的新功能给用户和开发者, 本文重点介绍面向开发者的一些新功能. 确保检查android 7.0的行为变化,了解有关平台的变化可能会影响你的app. 如果要了解更多的关于用户的新功能,请查看www.android.com. 1.支持多窗口 在android 7.0中,我们介绍了在支持多窗口

【译】Android 7.0 for Developers

译者注: 译者:aroundme 原文地址:https://developer.android.com/about/versions/nougat/android-7.0.html 主要是介绍Android 7.0提供新特性. 翻译的动机主要是为了适配Android 7.0,提前踩点.防止大坑. 就翻译来看,除去一些可有可无的更新之外,关注点主要是集中在四点: * 通知栏一系列更新 * 对于应用后台优化(或者说限制) * WebView持续性更新(混合开发需要注意) * 对于GPU的优化,优化3

Android 5.0 源代码结构

本节书摘来自异步社区<深入理解Android 5 源代码>一书中的第2章,第2.2节分析Android源代码结构,作者 李骏. 网址:https://yq.aliyun.com/articles/93279?spm=5176.100239.blogcont93310.17.gtBsUg 2.2 分析Android源代码结构 获得Android 5.0源代码后,源代码的全部工程分为以下3个部分. Core Project:核心工程部分,这是建立Android系统的基础,被保存在根目录的各个文件夹

Android 5.0之后屏幕截图的方法

截图的几种方法 Android获取屏幕截图主要有以下三种方法 1.通过view.getDrawingCache()获取指定View的绘制缓存来实现截屏. 这种方式Android 5.0之前也可以,且不需要权限.可以截取本应用内任意位置的屏幕截屏,可能会有些webview会截取不到. 注意这种方式只能获取当前应用内的截图(连顶部状态栏中的时间等都信息都获取不到,获取到的状态栏是一片空白). 2.通过Linux底层驱动来实现截屏. linux的图像信息都是通过FrameBuffer来写到显示设备上的

Android 6.0 动态权限申请注意事项

<span style="font-size:24px;color:#ffff00;background-color: rgb(0, 0, 153);"><strong>Android 6.0 权限区分</strong></span> Android 6.0 为了保护用户隐私,将一些权限的申请放在了应用运行的时候去申请, 比如以往的开发中,开发人员只需要将需要的权限在清单文件中配置即可,安装后用户可以在设置中的应用信息中看到:XX应用以获

Android 5.0特性

虽然此前Google对其已经做过了比较深入的介绍,但作为一个如此重要的升级版本,更新内容自然是海量的. Google今天很贴心地在官网上放出了Android 5.0正式版的完整更新日志,涵盖了升级的方方面面,不过说实话也只是一些重要的.大面上的概略更新介绍,还有更多细节等待挖掘. 1.Material Design 醒目的.多彩的.快速响应的UI设计,可为你所有的设备带来一致的直觉体验. - 响应快速.自然流畅的动作,真实的光照和阴影,熟悉的视觉元素,设备导航更加轻而易举. - 惊艳的新色彩,凸