Android端Firebase推送通知点击后停止循环播放音效问题求助
解决Firebase推送通知音效循环播放且点击无法停止的问题
我之前也碰到过一模一样的问题!核心原因大多是播放音效的实例(比如MediaPlayer)是局部创建的,当FirebaseMessagingService执行完onMessageReceived方法后,这个实例就找不到了,点击通知时自然没法调用停止方法。下面给你一套完整的解决方案:
第一步:全局持有音效播放实例
我们需要把MediaPlayer(或SoundPool)变成全局可访问的,这样不管是推送到来时播放,还是点击通知时停止,都能拿到同一个实例。推荐在Application类里维护单例:
class MyApp : Application() { companion object { // 全局持有MediaPlayer实例 var notificationMediaPlayer: MediaPlayer? = null } override fun onCreate() { super.onCreate() // 这里可以提前初始化,也可以在播放时再创建 } }
别忘了在AndroidManifest.xml里注册这个Application:
<application android:name=".MyApp" ...> ... </application>
第二步:在FirebaseMessagingService中播放音效并配置通知跳转
在onMessageReceived方法里,先停止之前可能在播放的音效,再初始化新的实例并循环播放;同时给通知的跳转Intent添加标记,告诉目标Activity需要停止音效:
class MyFirebaseMessagingService : FirebaseMessagingService() { override fun onMessageReceived(remoteMessage: RemoteMessage) { super.onMessageReceived(remoteMessage) // 先停止之前的音效,避免叠加播放 MyApp.notificationMediaPlayer?.let { if (it.isPlaying) { it.stop() } it.release() } // 初始化并开始循环播放音效 MyApp.notificationMediaPlayer = MediaPlayer.create(this, R.raw.your_notification_sound) MyApp.notificationMediaPlayer?.apply { isLooping = true start() } // 创建跳转Intent,添加停止音效的标记 val intent = Intent(this, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK putExtra("ACTION_STOP_NOTIFICATION_SOUND", true) } val pendingIntent = PendingIntent.getActivity( this, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ) // 构建并显示通知 val notification = NotificationCompat.Builder(this, "YOUR_CHANNEL_ID") .setSmallIcon(R.drawable.ic_notification) .setContentTitle(remoteMessage.notification?.title ?: "通知") .setContentText(remoteMessage.notification?.body ?: "新消息") .setPriority(NotificationCompat.PRIORITY_HIGH) .setContentIntent(pendingIntent) .setAutoCancel(true) .build() NotificationManagerCompat.from(this).notify(1001, notification) } // 服务销毁时释放MediaPlayer,防止内存泄漏 override fun onDestroy() { super.onDestroy() MyApp.notificationMediaPlayer?.let { if (it.isPlaying) it.stop() it.release() MyApp.notificationMediaPlayer = null } } }
第三步:在跳转的Activity中停止音效
当用户点击通知进入MainActivity时,读取Intent里的标记,停止并释放MediaPlayer:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 处理通知跳转的停止音效逻辑 handleNotificationIntent(intent) } // 如果Activity已经在后台,会调用onNewIntent override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) handleNotificationIntent(intent) } private fun handleNotificationIntent(intent: Intent?) { intent?.let { if (it.getBooleanExtra("ACTION_STOP_NOTIFICATION_SOUND", false)) { MyApp.notificationMediaPlayer?.let { mediaPlayer -> if (mediaPlayer.isPlaying) { mediaPlayer.stop() } mediaPlayer.release() MyApp.notificationMediaPlayer = null } } } } }
额外注意事项
- 如果你用的是SoundPool而不是MediaPlayer,逻辑类似:全局持有SoundPool实例和播放的streamId,点击通知时调用
soundPool.stop(streamId)。 - Android 12及以上版本,后台播放音效可能需要申请
FOREGROUND_SERVICE_MEDIA权限,记得在Manifest里添加:<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA" /> - 一定要记得释放MediaPlayer,否则会造成内存泄漏!
内容的提问来源于stack exchange,提问作者Shahzaib Khan
相关产品推荐
相关产品推荐

