Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
I am trying to capture the screen using MediaProjection API but my app is continuously crashing. I tried and giving this error:
java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
My service code:
class RecordService : Service() {
private var mServiceHandler: ServiceHandler? = null
private var mMediaProjection: MediaProjection? = null
private var mVirtualDisplay: VirtualDisplay? = null
private var mMediaRecorder: MediaRecorder? = null
private var resultCode = 0
private var data: Intent? = null
private var mScreenStateReceiver: BroadcastReceiver? = null
var isInitialized=false
private inner class ServiceHandler(looper: Looper?) : Handler(looper) {
override fun handleMessage(msg: Message?) {
if (resultCode == RESULT_OK) {
startRecording(resultCode, data)
} else {
}
}
}
override fun onCreate() {
// when the main app is being closed
val notificationIntent = Intent(this, RecordService::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0)
val notification: Notification = Notification.Builder(this)
.setContentTitle("DataRecorder")
.setContentText("Your screen is being recorded and saved to your phone.")
.setSmallIcon(R.drawable.ic_dialog_alert)
.setContentIntent(pendingIntent)
.setTicker("Tickertext")
.build()
isInitialized=true
startForeground(ONGOING_NOTIFICATION_ID, notification)
mScreenStateReceiver = MyBroadcastReceiver()
val screenStateFilter = IntentFilter()
screenStateFilter.addAction(Intent.ACTION_SCREEN_ON)
screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF)
screenStateFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED)
registerReceiver(mScreenStateReceiver, screenStateFilter)
val thread = HandlerThread(
"ServiceStartArguments",
THREAD_PRIORITY_BACKGROUND
)
thread.start()
val mServiceLooper = thread.looper
mServiceHandler = ServiceHandler(mServiceLooper)
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
Toast.makeText(this, "Starting recording service", Toast.LENGTH_SHORT).show()
resultCode = intent.getIntExtra(EXTRA_RESULT_CODE, 0)
data = intent.getParcelableExtra(EXTRA_DATA)
check(!(resultCode == 0 || data == null)) { "Result code or data missing." }
val msg = mServiceHandler!!.obtainMessage()
msg.arg1 = startId
mServiceHandler!!.sendMessage(msg)
return START_REDELIVER_INTENT
}
private fun startRecording(resultCode: Int, data: Intent?) {
val mProjectionManager =
applicationContext.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
mMediaRecorder = MediaRecorder()
val metrics = DisplayMetrics()
val wm =
applicationContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
wm.defaultDisplay.getRealMetrics(metrics)
val mScreenDensity = metrics.densityDpi
val displayWidth = metrics.widthPixels
val displayHeight = metrics.heightPixels
mMediaRecorder!!.setVideoSource(MediaRecorder.VideoSource.SURFACE)
mMediaRecorder!!.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
mMediaRecorder!!.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
mMediaRecorder!!.setVideoEncodingBitRate(8 * 1000 * 1000)
mMediaRecorder!!.setVideoFrameRate(15)
mMediaRecorder!!.setVideoSize(displayWidth, displayHeight)
val videoDir =
Environment.getExternalStoragePublicDirectory(DIRECTORY_MOVIES)
.absolutePath
val timestamp = System.currentTimeMillis()
var orientation = "portrait"
if (displayWidth > displayHeight) {
orientation = "landscape"
}
val filePathAndName =
videoDir + "/time_" + timestamp.toString() + "_mode_" + orientation + ".mp4"
mMediaRecorder!!.setOutputFile(filePathAndName)
try {
mMediaRecorder!!.prepare()
} catch (e: IllegalStateException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
if(isInitialized){
mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data!!)
val surface: Surface = mMediaRecorder!!.surface
mVirtualDisplay = mMediaProjection!!.createVirtualDisplay(
"MainActivity",
displayWidth,
displayHeight,
mScreenDensity,
VIRTUAL_DISPLAY_FLAG_PRESENTATION,
surface,
null,
null
)
mMediaRecorder!!.start()
Log.v(TAG, "Started recording")
}
}
companion object {
private const val TAG = "RECORDERSERVICE"
private const val EXTRA_RESULT_CODE = "resultcode"
private const val EXTRA_DATA = "data"
private const val ONGOING_NOTIFICATION_ID = 23
}
}
I did add android:foregroundServiceType="mediaProjection"
in Manifest as well but it is not working. I tried other similar questing but the issue is not resolved yet. Thanks