Screen mirroring or screen casting
For most users, screen mirroring and screen casting might just mean the same thing: presenting the content from phone or any other small device to TV. It’s crucial to know the difference though, if you’re integrating one of these into your own apps.

Screen Mirroring refers to showing your phone’s display on the TV as is. That means any clutter on the phone, navigation icons, and every other clickable item appears on the TV as well, even though on most TVs you can’t interact with those UI elements.

Screen Casting means showing only the meaningful content on the TV. It’s used when you want to play a full-screen video on TV while your phone is showing controls, or maybe show graphs and charts on TV while your phone displays data in tabular format.

Protocols
The top most common protocols used for casting are:

  1. ChromeCast (Google Cast)

  2. MiraCast

  3. AirPlay

  4. Amazon Fling

  5. DLNA

  6. DIAL

  7. Samsung SmartTV

We’ll focus on the first two of the list. I might soon add AirPlay and Amazon Fling also (although AirPlay works on Apple devices only).

MiraCast
MiraCast is essentially a screen-mirroring protocol. The typical use case is to mirror entire screen of your small device (phone or tablet), on a bigger device (TV). It is possible to override system behaviour and display our own (custom) views using MiraCast as well, which from a developer’s perspective will be a second screen being displayed on top of the mirrored screen.

On Android, MiraCast devices aren’t visible to app unless that MiraCast device is already selected to cast from the system settings (at least from Android 8.0).

Once a MiraCast device is selected from settings, the app can then use MediaRouter API or DisplayManager API to get hold of a Display object, which can then be provided to Presentation object.

You can look for the selected MiraCast device by checking for selected route in the onResume method of the Activity or a Fragment.

override fun onResume() {
findSelectedDevice()
}

private fun findSelectedDevice() {
val route = mediaRouter.selectedRoute
if (route.playbackType != PLAYBACK_TYPE_LOCAL && route.presentationDisplay != null) {
selectedDisplay = route.presentationDisplay
showPresentationDialog()
}
A Presentation object is just a common Android dialog, when you call its show() method, instead of being presented to screen, this dialog opens in fullscreen mode on the TV. Now you have any layout in that presentation dialog.

private fun showPresentationDialog() {
if (selectedDisplay == null)
return

if (presentationDialogFragment != null && presentationDialogFragment!!.presentationDisplay != selectedDisplay) {
    dismissPresentationDialog()
}

if (presentationDialogFragment == null) {
    presentationDialogFragment = MyCustomPresentation(this, selectedDisplay)
    try {
        presentationDialogFragment!!.show(activity!!.supportFragmentManager, "MY_PRESENTATION_DIALOG_FRAGMENT")
    }
    catch (e: WindowManager.InvalidDisplayException) {
        Toast.makeText(context, "Invalid cast display", Toast.LENGTH_LONG).show()
    }
}

}
Now create your own MyCustomPresentation class that inherits from Presentation.

You can also inherit from DialogFragment and then inside its nnCreateDialog return a Presentation object.

class MyCustomPresentation(private val display: Display) : DialogFragment() {
override fun onCreateDialog(savedInstanceBundle: Bundle?) : Dialog {
return Presentation(context, display)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return inflater.inflate(R.layout.my_layout, container, false)
}
}

#chromecast #kotlin #android #miracast

Casting custom content from Android app to TV (2020 approach)
6.35 GEEK