音频流 Android 应用程序中的 Exoplayer | exoplayer 从流媒体 url 播放多个音频

问题描述 投票:0回答:1

这是我在 MainActivity 上托管的片段代码:

class RadioPlayerFragment : Fragment() {

    private lateinit var player: SimpleExoPlayer
    private lateinit var mBinding: FragmentRadioPlayerBinding
    private var isPlaying: Boolean = false
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        mBinding = FragmentRadioPlayerBinding.inflate(inflater, container, false)
        return mBinding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        Log.d(TAG, "onViewCreated \n $isPlaying")
        isPlaying = SharedPrefs.getBoolean(requireContext(), "isPlaying")
        initializePlayer()
        updateUI()
        mBinding.btnPlayPause.setOnClickListener {
            if (isPlaying) {
                Log.d(TAG, "onViewCreated: $isPlaying pausing audio")
                pauseRadio()
            } else {
                Log.d(TAG, "onViewCreated: $isPlaying playing audio")
                playRadio()
            }
        }

        requireContext().registerReceiver(
            notificationActionReceiver, IntentFilter("ACTION_STOP")
        )
    }
    override fun onStart() {
        super.onStart()
        Log.d(TAG, "onStart")
        if (isPlaying) {
            Log.d(TAG, "onStart: isPlaying")
            player.playWhenReady = true
            updateUI()
            updateNotification()
        }
    }

    private fun initializePlayer() {
        if (::player.isInitialized && isPlaying) {
            player.stop()
            player.release()
        }

        player = SimpleExoPlayer.Builder(requireContext())
            .setTrackSelector(DefaultTrackSelector(requireContext()))
            .setLoadControl(DefaultLoadControl())
            .build()

             val mediaItem = MediaItem.fromUri(Uri.parse(Constants.k_STREAM_URL))

        player.setMediaItem(mediaItem)
        player.prepare()
        Log.d(TAG, "initializePlayer: $isPlaying")
        player.playWhenReady = false
    }
    private fun playRadio() {
        player.playWhenReady = true
        isPlaying = true
        SharedPrefs.setBoolean(requireContext(), "isPlaying", true)
        updateNotification()
        updateUI()
    }
    private fun pauseRadio() {
        player.playWhenReady = false
        isPlaying = false
        Log.d(TAG, "pauseRadio: $isPlaying")
        SharedPrefs.setBoolean(requireContext(), "isPlaying", false)
        updateNotification()
        updateUI()
    }
    private fun updateUI() {
        if (isPlaying) {
            mBinding.gif.setImageResource(R.drawable.vuplay)
            mBinding.btnPlayPause.setImageResource(R.drawable.stopbutton)
        } else {
            mBinding.gif.setImageResource(R.drawable.vustop)
            mBinding.btnPlayPause.setImageResource(R.drawable.playbutton)
        }
    }
    private fun updateNotification() {
        createNotificationChannel()

        val stopIntent = Intent(requireContext(), NotificationActionReceiver::class.java).apply {
            action = "ACTION_STOP"
        }
        val stopPendingIntent: PendingIntent = PendingIntent.getBroadcast(requireContext(), 0, stopIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)

        val notification = NotificationCompat.Builder(requireContext(), "radio_channel")
            .setContentTitle("GUGS FM is playing")
            .setContentText("App is running in the background")
            .setSmallIcon(R.drawable.logo_2)
            .addAction(R.drawable.stopbutton, "Stop", stopPendingIntent)
            .build()

        if (ActivityCompat.checkSelfPermission(
                requireContext(),
                Manifest.permission.POST_NOTIFICATIONS
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            return
        }
        NotificationManagerCompat.from(requireContext()).notify(1, notification)
    }
    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name = "Radio Channel"
            val descriptionText = "Channel for radio notifications"
            val importance = NotificationManager.IMPORTANCE_LOW
            val channel = NotificationChannel("radio_channel", name, importance).apply {
                description = descriptionText
            }
            val notificationManager = requireContext().getSystemService(NotificationManager::class.java)
            notificationManager.createNotificationChannel(channel)
        }
    }

    private val notificationActionReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            if (intent?.action == "ACTION_STOP") {
                pauseRadio()
            }
        }
    }

    companion object{
        val TAG = "RadioPlayerFragment"
    }
}

当我在此片段上使用它时,播放器工作正常,我的条件是,当我播放音频并导航到另一个片段时,它应该继续播放,当我返回时,如果它正在播放,则显示正在播放的 UI(如果它已停止)由我来完成,然后显示停止的 UI。

但是现在,发生的情况是,当我导航到另一个片段并返回时,它会显示相关的用户界面(如果正在播放,然后正在播放,如果暂停然后暂停),但是当我从其他片段返回并尝试停止音频时,它会更改UI通过更改按钮和gif,但音频不会停止,但在UI中它在前端停止,现在如果用户再次单击按钮播放,那么它会开始一次连续播放另一个音频2个音频,旧音频没有停止,现在又是新的。 仅在片段导航并返回后才会发生这种情况,否则启动和停止工作正常。

android kotlin android-fragments audio-streaming exoplayer
1个回答
0
投票

经过搜索和与几位Android开发人员讨论后找到了解决方案。 exoplayer 应始终在应用程序级别类中初始化,这将确保播放器顺利运行而无需创建多个实例。为应用程序创建一个应用程序类并在其中初始化 exoplayer,然后在片段和通知接收器中使用它解决了我的问题。

© www.soinside.com 2019 - 2024. All rights reserved.