Android 实现屏幕录制
创始人
2024-11-14 11:04:36
  1. 添加权限和服务声明

      
  2. 创建屏幕录制的 Service

    import 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()     } } 
  3. 启动和停止录制

    private 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)         }     } } 

相关内容

热门资讯

裸辞做“一人公司”,我后悔了 去年这个时候,一位以色列程序员正在东南亚旅行。他顺手把一个在脑子里转了很久的想法做成了产品,一个让任...
南京建成国内首个Pre-6G试... 4月21日,2026全球6G技术与产业生态大会在南京开幕。全息互动技术展台前,一名远在北京的工作人员...
超梵求职受邀参加“2025抖音... 超梵求职受邀参加“2025抖音巨量引擎成人教育行业生态大会”,探讨分享优质内容传播,服务万千学员。 ...
摩托罗拉Razr 2026(R... IT之家 4 月 22 日消息,摩托罗拉宣布新一代 Razr 折叠手机将于 4 月 29 日在美国发...
库克卸任,特纳斯领航:苹果新纪... 苹果首席执行官蒂姆·库克将卸任,硬件工程主管约翰·特纳斯将接任,苹果公司今天宣布此事。 库克将在夏季...