【问题标题】:Binding exoplayer from service to activity not working?将 exoplayer 从服务绑定到活动不起作用?
【发布时间】:2020-07-04 13:16:14
【问题描述】:

以下是我的服务类

class LocalAudioService : Service() {

     var player: SimpleExoPlayer? = null
    private var playerNotificationManager: PlayerNotificationManager? = null
    private var mediaSession: MediaSessionCompat? = null
    private var mediaSessionConnector: MediaSessionConnector? = null
    private var allInOneApplication: AllInOneApplication? = null

    private val binder = LocalBinder()

    override fun onDestroy() {
        mediaSession?.release()
        mediaSessionConnector?.setPlayer(null, null)
        playerNotificationManager?.setPlayer(null)
        player?.release()
        player = null
        super.onDestroy()
    }

    override fun onBind(p0: Intent?): IBinder? {
        return binder
    }

    fun getPlayerInstance(): SimpleExoPlayer? {
        if (player == null) {
            startPlayer()
        }
        return player
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if(player == null){
            startPlayer()
        }
        return START_STICKY
    }

    private fun startPlayer(){
        val videoTrackSelectionFactory = AdaptiveTrackSelection.Factory()
        val trackSelector = DefaultTrackSelector(this, videoTrackSelectionFactory)
        allInOneApplication = AllInOneApplication.getInstance()
        val renderersFactory = (application as AllInOneApplication).buildRenderersFactory(false)
        player =
            SimpleExoPlayer.Builder(this, renderersFactory).setTrackSelector(trackSelector).build()
        val dataSourceFactory = DefaultDataSourceFactory(
            this,
            Util.getUserAgent(this, getString(R.string.app_name))
        )


//        val cacheDataSourceFactory = CacheDataSourceFactory(
//            DownloadUtil.getCache(this),
//            dataSourceFactory,
//            CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR
//        )
        val concatenatingMediaSource = ConcatenatingMediaSource()
        allInOneApplication?.localAudios?.map {
            val mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory)
                .createMediaSource(it?.audioUri)
            concatenatingMediaSource.addMediaSource(mediaSource)
        }

        player?.prepare(concatenatingMediaSource)

        player?.playWhenReady = true

        playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
            this,
            AUDIO_CHANNEL_ID,
            R.string.audio_channel_name,
            R.string.audio_channel_name,
            NOTIFICATION_ID,
            object : MediaDescriptionAdapter {
                override fun createCurrentContentIntent(player: Player): PendingIntent? {
                    val intent = Intent(this@LocalAudioService, LocalAudioPlayer::class.java)
                    return PendingIntent.getActivity(
                        this@LocalAudioService,
                        0,
                        intent,
                        PendingIntent.FLAG_UPDATE_CURRENT
                    )
                }

                override fun getCurrentContentText(player: Player): CharSequence? {
                    return allInOneApplication?.localAudios?.get(player.currentWindowIndex)?.title
                }

                override fun getCurrentContentTitle(player: Player): CharSequence {
                    return allInOneApplication?.localAudios?.get(player.currentWindowIndex)?.title.toString()
                }

                override fun getCurrentLargeIcon(
                    player: Player,
                    callback: PlayerNotificationManager.BitmapCallback
                ): Bitmap? {
                    return BitmapFactory.decodeResource(resources, R.drawable.audio)
                }

            }, object : PlayerNotificationManager.NotificationListener {
                override fun onNotificationPosted(
                    notificationId: Int,
                    notification: Notification,
                    ongoing: Boolean
                ) {
                    startForeground(notificationId, notification)
                }

                override fun onNotificationCancelled(
                    notificationId: Int,
                    dismissedByUser: Boolean
                ) {
                    stopSelf()

                }
            }
        )

        playerNotificationManager?.setPlayer(player)

        mediaSession = MediaSessionCompat(this, MEDIA_SESSION_TAG)
        mediaSession?.isActive = true
        mediaSession?.sessionToken?.let { playerNotificationManager?.setMediaSessionToken(it) }

        mediaSessionConnector = MediaSessionConnector(mediaSession)


        mediaSessionConnector?.setQueueNavigator(object : TimelineQueueNavigator(mediaSession) {
            override fun getMediaDescription(
                player: Player?,
                windowIndex: Int
            ): MediaDescriptionCompat? {
                return allInOneApplication?.getMediaDescription(
                    this@LocalAudioService,
                    allInOneApplication?.localAudios?.get(windowIndex)
                )
            }

        })
        mediaSessionConnector?.setPlayer(player, null)

    }


    inner class LocalBinder : Binder() {
        val service: LocalAudioService
            get() = this@LocalAudioService
    }

}

以下是我的 Activity 类

class LocalAudioPlayer : AppCompatActivity() {

    private var localAudioService: LocalAudioService? = null
    private var mBound = false

    private val mConnection: ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) {
            val binder: LocalAudioService.LocalBinder = iBinder as LocalAudioService.LocalBinder
            localAudioService = binder.service
            mBound = true
            initializePlayer()
        }

        override fun onServiceDisconnected(componentName: ComponentName) {
            mBound = false
        }
    }

    private fun initializePlayer() {
        if (mBound) {
            val player: SimpleExoPlayer? = localAudioService?.getPlayerInstance()
            exoplayer_local_audio_player.player = player
        }
    }

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

        Intent(this,LocalAudioService::class.java).also {
            Util.startForegroundService(this,it)
            exoplayer_local_audio_player.useController = true
            exoplayer_local_audio_player.showController()
            exoplayer_local_audio_player.controllerAutoShow = true
            exoplayer_local_audio_player.controllerHideOnTouch = false
        }
    }

    override fun onStart() {
        super.onStart()
        bindService(intent,mConnection, Context.BIND_AUTO_CREATE)
        initializePlayer()
        //TODO do any UI setup
    }

    override fun onStop() {
        unbindService(mConnection)
        mBound = false
        super.onStop()
    }
}

我尝试关注这个问题Binding PlayerView with SimpleExoPlayer from a service,但鞋底对我不起作用

【问题讨论】:

标签: android kotlin android-activity exoplayer2.x android-service-binding


【解决方案1】:

试试这个:

override fun onStart() {
    super.onStart()
    Intent(this, LocalAudioService::class.java).also { intent ->
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
    }
}

initializePlayer() 不应在此处调用。目前该服务尚未绑定。当服务绑定时,它会在 onServiceConnected 回调中调用。

【讨论】:

    【解决方案2】:
     bindService(intent,mConnection, Context.BIND_AUTO_CREATE)
    

    intent 在这里为空。请确保您获得正确且非空的意图。它应该像参考示例中那样全局声明

      intent = new Intent(this, AudioPlayerService.class);
    

    这里的意图是全局声明的。

    【讨论】:

      猜你喜欢
      • 2020-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-27
      • 1970-01-01
      • 2012-01-15
      • 2021-12-09
      相关资源
      最近更新 更多