Requirements

Android SDK v21

WRITE_EXTERNAL_STORAGE and RECORD_AUDIO permissions

Accepting

The first step is to request permission to capture the screen.

val manager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager startActivityForResult(manager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION)

Launching this intent will show a confirmation dialog to the user which allows them to authorise the screen capturing.

Once they accept, you can use the result code and data intent returned in onActivityResult, we are able to create a MediaProjection.

projection = manager.getMediaProjection(resultCode, data) as MediaProjection

Recording

Next we need to define our MediaRecorder. I’m not too fussed about the specific details so I used the predefined high quality CamcorderProfile but you can create your own and specify everything from output format to bits per second. One slightly different thing is that I defined the height and width using the Window’s DisplayMetrics so it exactly matched the screen size.

mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT)

mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE)

val profile: CamcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)

profile.videoFrameHeight = metrics.heightPixels

profile.videoFrameWidth = metrics.widthPixels

mMediaRecorder.setProfile(profile)

mMediaRecorder.setOutputFile(filename)

mMediaRecorder.prepare()

One gotcha about the MediaRecorder is that the methods have to be defined in the correct order. For example, once setting the Camcorder Profile, you can’t change the AudioSource without crashing. The javadoc has more details to the state machine behind this.

Mirroring

Once we have the MediaRecorder and MediaProjection, we can create a virtual display that mirrors the projection and then bind it to the MediaRecorder’s SurfaceView. If you weren’t interested in the recording aspect of this demo, you could bind to your own SurfaceView.

mVirtualDisplay = mMediaProjection!!.createVirtualDisplay(VIRTUAL_DISPLAY_NAME,

metrics.widthPixels, metrics.heightPixels, metrics.densityDpi,

DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,

mMediaRecorder.surface, null, null)

Now everything is set up, tell the MediaRecorder to start() recording and you’ll notice the cast icon appear in your phone’s status bar.

When you’re ready, call stop(). It’s also important to release the MediaProjection and VirtualDisplay too. The recording will then be saved to the location you define in setOutputFile.