-
添加权限和服务声明
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
相关推荐
晨春计28 分钟前
【git】标标大人1 小时前
c语言中的局部跳转以及全局跳转木鬼与槐2 小时前
MySQL高阶1783-大满贯数量iofomo2 小时前
【Abyss】Android 平台应用级系统调用拦截框架AirDroid_cn5 小时前
在家找不到手机?除了语音助手,还可以用远程控制!Good_tea_h13 小时前
Android中如何处理运行时权限?冬田里的一把火313 小时前
[Android][Reboot/Shutdown] 重启/关机 分析大海..13 小时前
Android 系统开发人员的权限说明文档技术无疆16 小时前
ButterKnife:Android视图绑定的简化专家JohnsonXin17 小时前
【兼容性记录】video标签在 IOS 和 安卓中的问题