Android TV - Exoplayer 控件显示在模拟器上但不显示在电视上

Posted

技术标签:

【中文标题】Android TV - Exoplayer 控件显示在模拟器上但不显示在电视上【英文标题】:Android TV - Exoplayer controls show on emulator but not on TV 【发布时间】:2021-01-07 06:03:18 【问题描述】:

我是一个相对初学者。我创建了一个简单的 exoplayer 活动来在 android TV 上播放 HLS 流。它可以正常加载和播放,当控件显示时,我可以暂停、播放、倒带、快进。在 android studio 模拟器 (Android TV API 28) 上,一旦控件隐藏起来,我可以单击模拟器并取消隐藏控件,所以一切都按预期工作。

在我的设备 (Nvidia Shield) 上,一切正常,直到控件隐藏。单击遥控器不会再次显示播放控件。我一直在寻找解决方案,我发现一些关于胶水等的提及,但这些页面提供了部分解决方案。我还没有找到任何关于如何在 Android TV 上实现 exoplayer 的教程。而且由于我是初学者,我真的可以使用指南。我能找到的所有指南都是关于在 Android 中实现 exoplayer 的——这就是我得到以下内容的方式。我发现唯一对我有意义的指南是这个 (https://rileymacdonald.ca/2017/09/21/android-tv-how-to-add-leanback-media-controls-to-google-exoplayer/) - 但它很旧而且不起作用。而且我不确定我是否必须实现leanback控件,或者只能使用exoplayer中的那些?非常感谢更新指南或帮助我解决单击遥控器时控件未重新显示的问题。

清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.exoplayertest">

    <uses-feature
        android:name="android.software.leanback"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.touchscreen"
        android:required="false" />

    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:banner="@drawable/tv">
        <activity android:name=".MainActivity"
            android:configChanges="keyboard|keyboardHidden|navigation">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/flRoot"
        android:focusable="true"
        android:layout_
        android:layout_
        android:keepScreenOn="true">
    
        <com.google.android.exoplayer2.ui.PlayerView
            android:id="@+id/playerView"
            android:focusable="true"
            android:layout_
            android:layout_>
    
            <ProgressBar
                android:id="@+id/progressBar"
                android:layout_
                android:layout_
                android:layout_gravity="center"
                android:visibility="gone"/>
    
        </com.google.android.exoplayer2.ui.PlayerView>

</FrameLayout>  

MainActivity.kt

class MainActivity : Activity() 

    private var mPlayer: SimpleExoPlayer? = null
    private val hlsUrl = "https://9now-livestreams.akamaized.net/hls/live/2010628/rush-mel/master.m3u8"

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

    

    private fun initPlayer() 
        mPlayer = SimpleExoPlayer.Builder(this).build()
        // Bind the player to the view.
        playerView.player = mPlayer
        mPlayer!!.playWhenReady = true
        //mPlayer!!.seekTo(playbackPosition)
        mPlayer!!.prepare(buildMediaSource(), false, false)

    

    override fun onStart() 
        super.onStart()

        initPlayer()
    

    override fun onResume() 
        super.onResume()
        hideSystemUi()
        if (mPlayer == null) 
            initPlayer()
        
    

    override fun onPause() 
        super.onPause()
    

    override fun onStop() 
        super.onStop()

        releasePlayer()
    

    @SuppressLint("InlinedApi")
    private fun hideSystemUi() 
        playerView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LOW_PROFILE
                or View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)
    

    private fun releasePlayer() 
        if (mPlayer == null) 
            return
        
        mPlayer!!.release()
        mPlayer = null
    

    private fun buildMediaSource(): MediaSource 
        val userAgent =
            Util.getUserAgent(playerView.context, playerView.context.getString(R.string.app_name))

        val dataSourceFactory = DefaultHttpDataSourceFactory(userAgent)
        val hlsMediaSource =
            HlsMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.parse(hlsUrl))

        return hlsMediaSource
    

【问题讨论】:

【参考方案1】:

我不确定为什么会出现问题(或者即使这是正常行为),但如果有人遇到类似问题,我将以下内容添加到我的 PlayerActivity 类中,它现在可以工作了。

override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean 
    when (keyCode) 
        KeyEvent.KEYCODE_DPAD_CENTER -> 
            if (!playerView.isControllerVisible()) 
                playerView.showController()
            
            return true
        
    
    return super.onKeyDown(keyCode, event)

【讨论】:

以上是关于Android TV - Exoplayer 控件显示在模拟器上但不显示在电视上的主要内容,如果未能解决你的问题,请参考以下文章

Android TV Leanback Exoplayer 视频缩放问题

Android TV 中的 ExoPlayer 以纵向模式而不是横向模式播放视频

android tv 中的 Exoplayer 不会在直播中重现 (.m3u8) 文件

Android 和 Exoplayer 中的视图绑定

React Native Android TV 控件

Android TV开发焦点移动源码分析