推荐阅读:
一年Android开发经验,知乎网易蘑菇街阿里面经,已拿网易offer
Android开发该何去何从——来自安卓程序员的焦虑
2019年字节跳动腾讯Android面试必问:性能优化+JNI+布局+WebView
Android 从 4.0 开始就提供了手机录屏方法,但是需要 root 权限,比较麻烦不容易实现。但是从 5.0 开始,系统提供给了 App 录制屏幕的一系列方法,不需要 root 权限,只需要用户授权即可录屏,相对来说较为简单。
基本上根据 官方文档 便可以写出录屏的相关代码。
屏幕录制的基本实现步骤
在 Manifest 中申明权限
获取 MediaProjectionManager 并申请权限
private val mediaProjectionManager by lazy { activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as? MediaProjectionManager }private var mediaProjection: MediaProjection? = nullif (mediaProjectionManager == null) { Log.d(TAG, "mediaProjectionManager == null,当前手机暂不支持录屏") showToast(R.string.phone_not_support_screen_record) return}// 申请相关权限PermissionUtils.permission(PermissionConstants.STORAGE, PermissionConstants.MICROPHONE) .callback(object : PermissionUtils.SimpleCallback { override fun onGranted() { Log.d(TAG, "start record") mediaProjectionManager?.apply { // 申请相关权限成功后,要向用户申请录屏对话框 val intent = this.createScreenCaptureIntent() if (activity.packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) { activity.startActivityForResult(intent, REQUEST_CODE) } else { showToast(R.string.phone_not_support_screen_record) } } } override fun onDenied() { showToast(R.string.permission_denied) } }) .request()
重写 onActivityResult() 对用户授权进行处理
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { if (requestCode == REQUEST_CODE) { if (resultCode == Activity.RESULT_OK) { mediaProjection = mediaProjectionManager!!.getMediaProjection(resultCode, data) // 实测,部分手机上录制视频的时候会有弹窗的出现,所以我们需要做一个 150ms 的延迟 Handler().postDelayed({ if (initRecorder()) { mediaRecorder?.start() } else { showToast(R.string.phone_not_support_screen_record) } }, 150) } else { showToast(R.string.phone_not_support_screen_record) } }}private fun initRecorder(): Boolean { Log.d(TAG, "initRecorder") var result = true // 创建文件夹 val f = File(savePath) if (!f.exists()) { f.mkdirs() } // 录屏保存的文件 saveFile = File(savePath, "$saveName.tmp") saveFile?.apply { if (exists()) { delete() } } mediaRecorder = MediaRecorder() val width = Math.min(displayMetrics.widthPixels, 1080) val height = Math.min(displayMetrics.heightPixels, 1920) mediaRecorder?.apply { // 可以设置是否录制音频 if (recordAudio) { setAudioSource(MediaRecorder.AudioSource.MIC) } setVideoSource(MediaRecorder.VideoSource.SURFACE) setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setVideoEncoder(MediaRecorder.VideoEncoder.H264) if (recordAudio){ setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB) } setOutputFile(saveFile!!.absolutePath) setVideoSize(width, height) setVideoEncodingBitRate(8388608) setVideoFrameRate(VIDEO_FRAME_RATE) try { prepare() virtualDisplay = mediaProjection?.createVirtualDisplay("MainScreen