- 添加权限和服务声明
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <service android:name=".ScreenService" android:enabled="true" android:exported="true" android:foregroundServiceType="mediaProjection"></service>
- 创建屏幕录制的 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() } }
- 启动和停止录制
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) } } }
Android 实现屏幕录制
Android 实现屏幕录制创建屏幕录制的 Service
FFmpeg屏幕录制
上一篇
2025-01-02 12:57
游戏AI之有限状态机
下一篇
2025-01-02 12:51
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/99692.html