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