-
添加权限和服务声明
xml<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <service android:name=".ScreenService" android:enabled="true" android:exported="true" android:foregroundServiceType="mediaProjection"></service> -
创建屏幕录制的 Service
kotlinimport android.app.* import android.content.Context import android.content.Intent import android.graphics.BitmapFactory import android.hardware.display.DisplayManager import android.hardware.display.VirtualDisplay import android.media.CamcorderProfile import android.media.MediaRecorder import android.media.projection.MediaProjection import android.media.projection.MediaProjectionManager import android.os.Build import android.os.IBinder import android.util.DisplayMetrics import android.util.Log import android.view.WindowManager import androidx.core.app.NotificationCompat import java.io.IOException class ScreenService : Service() { private var mContext:Context?=null private var projectionManager:MediaProjectionManager?=null private var mMediaProjection:MediaProjection?=null override fun onBind(intent: Intent): IBinder { TODO("Return the communication channel to the service.") } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { mContext = this var resultCode = intent?.getIntExtra("resultCode", -1) var path = intent?.getStringExtra("path") var resultData: Intent? = intent?.getParcelableExtra("data") startNotification(); projectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager mMediaProjection = resultCode?.let { resultData?.let { it1 -> projectionManager?.getMediaProjection(it, it1) } } path?.let { startRecording(it) } return super.onStartCommand(intent, flags, startId) } private var NOTIFICATION_CHANNEL_ID="id"; private var NOTIFICATION_CHANNEL_NAME="channel"; private var NOTIFICATION_CHANNEL_DESC="desc"; private fun startNotification() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { var notificationIntent = Intent(mContext, ScreenService::class.java) var pendingIntent: PendingIntent?=null pendingIntent = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE); } else { PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_ONE_SHOT); } var notificationBuilder = mContext?.let { NotificationCompat.Builder(it, NOTIFICATION_CHANNEL_ID) .setLargeIcon(BitmapFactory.decodeResource(mContext!!.resources, R.drawable.ic_launcher_foreground)) .setSmallIcon(R.drawable.ic_launcher_foreground) .setContentTitle("start record") .setContentText("=== start record ===") .setContentIntent(pendingIntent) }; var notification = notificationBuilder?.build(); var channel = NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT); channel.description = NOTIFICATION_CHANNEL_DESC; var notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.createNotificationChannel(channel) startForeground(1, notification); } } private var isScreenRecoding = false private var mMediaRecorder: MediaRecorder?=null private var mVirtualDisplay: VirtualDisplay? = null private fun startRecording(filePath:String) { if (!isScreenRecoding){ try { // 创建 MediaRecorder 并设置参数 val metrics = DisplayMetrics() val windowManager: WindowManager = mContext?.getSystemService(WINDOW_SERVICE) as WindowManager windowManager.defaultDisplay.getMetrics(metrics) mMediaRecorder = MediaRecorder() mMediaRecorder?.setVideoSource(MediaRecorder.VideoSource.SURFACE) mMediaRecorder?.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) mMediaRecorder?.setOutputFile(filePath) mMediaRecorder?.setVideoSize(metrics.widthPixels, metrics.heightPixels) mMediaRecorder?.setVideoEncoder(MediaRecorder.VideoEncoder.H264) mMediaRecorder?.setVideoEncodingBitRate(1920*1080 * 3) mMediaRecorder?.setVideoFrameRate(30) // 准备 MediaRecorder mMediaRecorder?.prepare() // 创建 VirtualDisplay 以获取屏幕内容 mVirtualDisplay = mMediaProjection?.createVirtualDisplay( "ScreenRecord", metrics.widthPixels, metrics.heightPixels, metrics.densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mMediaRecorder?.surface, null, null ) // 开始录制 mMediaRecorder?.start() isScreenRecoding = true Log.i(ScreenUtil.TAG,"开始录屏 $filePath") } catch (e: IOException) { Log.e(ScreenUtil.TAG, "录屏失败: " + e.message) e.printStackTrace() } } } public fun stopRecording() { if (isScreenRecoding) { try { // 停止录制 mMediaRecorder?.stop() mMediaRecorder?.reset() mMediaRecorder?.release() mMediaRecorder = null // 停止 VirtualDisplay mVirtualDisplay?.release() // 停止 MediaProjection mMediaProjection?.stop() Log.i(ScreenUtil.TAG,"结束录屏") } catch (e: Exception) { Log.e(ScreenUtil.TAG, "停止录屏失败: " + e.message) e.printStackTrace() } isScreenRecoding = false } } override fun onDestroy() { stopRecording() super.onDestroy() } } -
启动和停止录制
kotlinprivate var mProjectionManager: MediaProjectionManager? = null var screenService:Intent?=null fun start(){ mProjectionManager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager // 请求录屏权限 startActivityForResult(mProjectionManager?.createScreenCaptureIntent(), 500); } fun stop(){ stopService(screenService) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == 500){ screenService = Intent(mConext, ScreenService::class.java) screenService?.let { it.putExtra("resultCode", resultCode); it.putExtra("data", data); it.putExtra("path", "screen.mp4"); startForegroundService(it) } } }
Android 实现屏幕录制
菠萝加点糖2024-08-03 23:39
相关推荐
plainGeekDev8 小时前
文件读写(Java IO)→ Kotlin 扩展函数s_nshine9 小时前
释放C盘,迁移studio相关数据到其他盘韩曙亮9 小时前
【Flutter】Flutter 中的 Android / iOS 特殊配置 ① ( 网络权限配置 | HTTP 明文传输配置 | 应用名称配置 )_李小白9 小时前
【android opencv学习笔记】Day 31:提取轮廓之Canny算法hashiqimiya10 小时前
每日android布局xml文件m0_7381207211 小时前
渗透测试基础——PHP 序列化数据结构与反序列化机制详解故渊at11 小时前
第二板块:Android 四大组件标准化学理 | 第十一篇:组件间通信(IPC)与 Binder 深度解析ZC跨境爬虫11 小时前
跟着 MDN 学JavaScript day_10:数组——数据的有序集合消失的旧时光-194312 小时前
Kotlin 协程设计思想(九):Flow 到底是什么?为什么 suspend 函数还需要 Flow?