美文网首页ReplayKit
iOS-Swift使用ReplayKit实现录屏功能

iOS-Swift使用ReplayKit实现录屏功能

作者: Janise001 | 来源:发表于2019-01-11 18:01 被阅读0次

    前段时间有碰到Android用户使用系统录屏发来的一些bug重现录像,iOS端不会用系统录屏的用户都是拍视频联系产品然后反馈给我们开发,这中间有的时候挺耗费时间和精力的,空下来就琢磨了下iOS的录屏使用。录屏用得比较多的是苹果自带的ReplayKit框架,不需要导包,使用比较便捷,而且耗费内存较小,基本忽略不计,这也是我选择ReplayKit的原因,如对功能研究较感兴趣的同学可以忽略本篇。
    我使用的手机是锤子M1的是比较老的版本,我对照着锤子做了一个简单的demo,效果图如下:


    效果图

    系统版本9.0以下ReplayKit是不可使用的,所以在使用前一定要判断系统版本是否符合要求,在Targets->Build Settings->iOS Deployment Target中设置的版本号高于9.0也可使用,也可加if #avaliable(iOS 9.0,*)判断减少此类风险,这边是个大坑,我写的demo中Timer等需要10.0以上版本,所以请勿抬杠,个人因情况而定。


    Targets->Build Settings->iOS Deployment Target
    工具条对应的文件

    “展示录屏控件”触发方法,在给ReplayToolsView中的关闭按钮和录屏开始按钮加事件的时候我是使用的闭包,这样可以控制效果图中红色按钮的状态;对红色按钮的状态判断是为了避免多次点击按钮后ReplayToolsView的叠加;replayVideoView.addGestureRecognizer给replayVideoView添加移动手势,王者荣耀中在录屏时按钮是固定的,以下demo中的录屏可以在整个app中使用,包括记录页面跳转过程等。

    @IBAction func showActionView(_ sender: UIButton) {
            if !self.showViewBtn.isSelected {
                let replayVideoView = ReplayToolsView(frame: CGRect(x: 20, y: self.view.bounds.height-100, width: self.view.bounds.width-40, height: 50))
                //使用block代替在view中编写关闭方法,添加对“app录屏”按钮的选中状态设置
                replayVideoView.closeBlock = { () in
                    //此处设置结束录制后将replayVideoView移除,也可以隐藏isHidden,在此处和startRecordingScreen方法中将view改成隐藏,replayVideoView需要改为全局变量使用
                    replayVideoView.removeFromSuperview()
                    self.showViewBtn.isSelected = !self.showViewBtn.isSelected
                }
                replayVideoView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(dragFunction)))
                replayVideoView.actionBlock = {
                    self.startRecordingScreen(replayVideoView)
                    replayVideoView.closeButton.isHidden = replayVideoView.actionButton.isSelected
                }
                let window = UIApplication.shared.keyWindow
                window!.addSubview(replayVideoView)
                self.showViewBtn.isSelected = !self.showViewBtn.isSelected
            }
        }
    
     // Janise: 设置拖动手势(可用于拖动控件后设置控件依赖位置,此处只设置可在y轴方向上移动,如需要在x方向上移动,可对x位置修改)
        @objc func dragFunction(_ pan: UIPanGestureRecognizer) {
            let point = pan.translation(in: view)
            if let v = pan.view {
                //设置移至顶部和底部时不可移动,64为个人主观设置值,可根据个人需要更改
                if (v.frame.origin.y > 64 && point.y < 0)
                    || (v.frame.origin.y + v.frame.height < (UIApplication.shared.keyWindow?.frame.height)! && point.y > 0) {
                    v.center.y = v.center.y + point.y
                }
                pan.setTranslation(.zero, in: view)
            }
        }
    
     // Janise:  开始录制屏幕(考虑问题,可否像android那样在录屏时不将ReplayVideoToolView视图作为屏幕的一部分录制,我暂时还没找到方法)
        
        /// 开始录屏(遗留问题:初次录屏时会询问用户是否同意使用录屏功能,但是时间在用户点击录屏按钮时已开始计时,与用户同意使用录屏功能时间点有时间差,这部分需要解决)
        ///
        /// - Parameter toolView: 自制黑色半透明录屏视图(用于图标的展示修改和时间的变化)
        @objc func startRecordingScreen(_ toolView: ReplayToolsView) {
            // 检测设备是否支持录屏功能
            if RPScreenRecorder.shared().isAvailable && systemVersionAvaliable()  {
                //录屏按钮是否选中
                if toolView.actionButton.isSelected {
                    //停止计时
                    self.time?.invalidate()
                    self.time = nil
                    toolView.seconds = 0
                    //选中状态下停止录制
                    RPScreenRecorder.shared().stopRecording { (previewCon, error) in
                        if let errors = error {
                            print(errors)
                        }
                        if let controller = previewCon {
                            controller.previewControllerDelegate = self
                            UIApplication.shared.keyWindow?.rootViewController?.present(controller, animated: true, completion: nil)
                        }
                    }
                    
                    toolView.actionButton.isSelected = false
                    toolView.removeFromSuperview()
                    self.showViewBtn.isSelected = !self.showViewBtn.isSelected
                    return
                }else {
                    //开始计时
                    self.time = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true, block: { (timer) in
                        toolView.seconds += 1
                    })
                    //未选中状态下开始录屏
                    RPScreenRecorder.shared().startRecording { (err) in
                        if let error = err {
                            print(error)
                        }
                    }
                    toolView.actionButton.isSelected = true
                }
            }else {
                //            //正式编写时需将两种提示分开展示,权限与版本两个不可合二为一
                //            let alert = UIAlertController(title: "提示", message: "请先授予app录屏权限,系统版本低于9.0不支持录屏功能,请升级版本后使用该功能", preferredStyle: .alert)
                //            self.present(alert, animated: true, completion: nil)
            }
        }
    
    /// 视频播放
        ///
        /// - Parameter previewController: 视频预览播放器
        func previewControllerDidFinish(_ previewController: RPPreviewViewController) {
            //关闭视频预览
            previewController.dismiss(animated: true, completion: nil)
        }
    
    /// 判断版本是否在9.0版本及以上版本
        ///
        /// - Returns: 布尔值
        func systemVersionAvaliable() -> Bool {
            if #available(iOS 9.0, *) {
                return true
            }
            return false
        }
    

    replayVideoView的编写较为简单,此处不做展示。
    我没有添加麦克风录音功能,startRecording(withMicrophoneEnabled:true...在10.0版本已被弃用,我在找其他的方法来替代。

    RPScreenRecorder.shared().startRecording(withMicrophoneEnabled:true) { (<#Error?#>)in
                        <#code#>
                    }
    

    ReplayKit不可以与AVPlayer同用,会出现兼容问题,录屏功能只能在真机上使用,虚拟机不支持,我是用的Swift编写,网上较多的使用OC,IOS 一个很好的录制屏幕实现IOS功能 - 飞翔的熊blabla - CSDN博客csdn上这篇写得比较好。

    以上代码我传到了GitHub上,地址是demo

    相关文章

      网友评论

        本文标题:iOS-Swift使用ReplayKit实现录屏功能

        本文链接:https://www.haomeiwen.com/subject/mqxfdqtx.html