override fun onCreate()

in ClassicsKotlin/app/src/main/java/com/android/tv/classics/fragments/NowPlayingFragment.kt [173:304]


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        backgroundType = PlaybackSupportFragment.BG_NONE
        database = TvMediaDatabase.getInstance(requireContext())
        val metadata = args.metadata

        // Adds this program to the continue watching row, in case the user leaves before finishing
        val programUri = TvLauncherUtils.upsertWatchNext(requireContext(), metadata)
        if (programUri != null) lifecycleScope.launch(Dispatchers.IO) {
            database.metadata().update(metadata.apply { watchNext = true })
        }

        // Initializes the video player
        player = ExoPlayerFactory.newSimpleInstance(requireContext())
        mediaSession = MediaSessionCompat(requireContext(), getString(R.string.app_name))
        mediaSessionConnector = MediaSessionConnector(mediaSession)

        // Listen to media session events. This is necessary for things like closed captions which
        // can be triggered by things outside of our app, for example via Google Assistant
        mediaSessionConnector.setCaptionCallback(object : MediaSessionConnector.CaptionCallback {
            override fun onCommand(player: Player, controlDispatcher: ControlDispatcher, command: String, extras: Bundle?, cb: ResultReceiver?): Boolean {
                return false
            }

            override fun hasCaptions(player: Player): Boolean {
                // TODO(owahltinez): handle captions
                return true
            }

            override fun onSetCaptioningEnabled(player: Player, enabled: Boolean) {
                // TODO(owahltinez): handle captions
                Log.d(TAG, "onSetCaptioningEnabled() enabled=$enabled")
            }
        })
        mediaSessionConnector.setRatingCallback(object : MediaSessionConnector.RatingCallback {
            override fun onCommand(player: Player, controlDispatcher: ControlDispatcher, command: String, extras: Bundle?, cb: ResultReceiver?): Boolean {
                return false
            }

            override fun onSetRating(player: Player, rating: RatingCompat) {
                // TODO(plammer): handle ratings
                Log.d(TAG, "onSetRating() rating=$rating")
            }

            override fun onSetRating(player: Player, rating: RatingCompat, extras: Bundle) {
                // TODO(plammer): handle ratings
                Log.d(TAG, "onSetRating() rating=$rating")
            }
        })

        // Links our video player with this Leanback video playback fragment
        val playerAdapter = LeanbackPlayerAdapter(
                requireContext(), player, PLAYER_UPDATE_INTERVAL_MILLIS)

        // Enables pass-through of transport controls to our player instance
        playerGlue = MediaPlayerGlue(requireContext(), playerAdapter).apply {
            host = VideoSupportFragmentGlueHost(this@NowPlayingFragment)

            // Adds playback state listeners
            addPlayerCallback(object : PlaybackGlue.PlayerCallback() {

                override fun onPreparedStateChanged(glue: PlaybackGlue?) {
                    super.onPreparedStateChanged(glue)
                    if (glue?.isPrepared == true) {
                        // When playback is ready, skip to last known position
                        val startingPosition = metadata.playbackPositionMillis ?: 0
                        Log.d(TAG, "Setting starting playback position to $startingPosition")
                        seekTo(startingPosition)
                    }
                }

                override fun onPlayCompleted(glue: PlaybackGlue?) {
                    super.onPlayCompleted(glue)

                    // Don't forget to remove irrelevant content from the continue watching row
                    TvLauncherUtils.removeFromWatchNext(requireContext(), args.metadata)

                    // When playback is finished, go back to the previous screen
                    val navController = Navigation.findNavController(
                            requireActivity(), R.id.fragment_container)
                    navController.currentDestination?.id?.let {
                        navController.popBackStack(it, true)
                    }
                }
            })

            // Begins playback automatically
            playWhenPrepared()

            // Displays the current item's metadata
            setMetadata(metadata)
        }

        // Setup the fragment adapter with our player glue presenter
        adapter = ArrayObjectAdapter(playerGlue.playbackRowPresenter).apply {
            add(playerGlue.controlsRow)
        }

        // Adds key listeners
        playerGlue.host.setOnKeyInterceptListener { view, keyCode, event ->

            // Early exit: if the controls overlay is visible, don't intercept any keys
            if (playerGlue.host.isControlsOverlayVisible) return@setOnKeyInterceptListener false

            // TODO(owahltinez): This workaround is necessary for navigation library to work with
            //  Leanback's [PlaybackSupportFragment]
            if (!playerGlue.host.isControlsOverlayVisible &&
                    keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_DOWN) {
                Log.d(TAG, "Intercepting BACK key for fragment navigation")
                val navController = Navigation.findNavController(
                        requireActivity(), R.id.fragment_container)
                navController.currentDestination?.id?.let { navController.popBackStack(it, true) }
                return@setOnKeyInterceptListener true
            }

            // Skips ahead when user presses DPAD_RIGHT
            if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT && event.action == KeyEvent.ACTION_DOWN) {
                playerGlue.skipForward()
                preventControlsOverlay(playerGlue)
                return@setOnKeyInterceptListener true
            }

            // Rewinds when user presses DPAD_LEFT
            if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT && event.action == KeyEvent.ACTION_DOWN) {
                playerGlue.skipBackward()
                preventControlsOverlay(playerGlue)
                return@setOnKeyInterceptListener true
            }

            false
        }
    }