Android接收OneSignal呼叫通知时播放45秒铃声的实现方案
OneSignal呼叫通知播放铃声方案及替代实现
OneSignal原生支持情况
- OneSignal本身不直接提供持续播放自定义时长铃声的功能,它的通知声音是系统级短提示音,依赖系统通知渠道的声音设置,无法控制播放时长到45秒这类自定义需求。
- 但可以通过OneSignal的通知接收回调触发自定义铃声播放逻辑,这是实现需求的核心路径。
自定义铃声播放实现(Android端)
1. 监听OneSignal通知接收事件
在应用中注册通知接收监听器,识别呼叫通知后启动音频播放:
OneSignal.setNotificationWillShowInForegroundHandler(new NotificationWillShowInForegroundHandler() { @Override public void notificationWillShowInForeground(OSNotificationReceivedEvent event) { // 通过自定义字段判断是否为呼叫通知 if ("call_notification".equals(event.getNotification().getAdditionalData().optString("type"))) { startCallRingtone(); } event.complete(event.getNotification()); } });
2. 实现45秒时长的铃声播放
提供两种原生实现方案:
方案一:MediaPlayer(自定义铃声文件)
private MediaPlayer mediaPlayer; private void startCallRingtone() { try { // 从raw资源加载铃声文件 mediaPlayer = MediaPlayer.create(this, R.raw.call_ringtone); mediaPlayer.setLooping(false); mediaPlayer.start(); // 45秒后自动停止 new Handler(Looper.getMainLooper()).postDelayed(() -> { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.stop(); mediaPlayer.release(); mediaPlayer = null; } }, 45000); } catch (Exception e) { e.printStackTrace(); } }
注意:需在接听/拒接按钮的点击事件中同步停止铃声播放。
方案二:RingtoneManager(系统来电铃声)
如果想用系统默认铃声:
private Ringtone callRingtone; private void startCallRingtone() { Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE); callRingtone = RingtoneManager.getRingtone(this, ringtoneUri); callRingtone.play(); // 45秒后自动停止 new Handler(Looper.getMainLooper()).postDelayed(() -> { if (callRingtone != null && callRingtone.isPlaying()) { callRingtone.stop(); } }, 45000); }
iOS端实现思路
通过OneSignal的通知回调触发音频播放,使用AVAudioPlayer实现自定义时长逻辑:
import AVFoundation var audioPlayer: AVAudioPlayer? func notificationWillDisplay(_ notification: OSNotification, with completionHandler: @escaping (OSNotificationDisplayType) -> Void) { if let type = notification.additionalData?["type"] as? String, type == "call_notification" { startCallRingtone() } completionHandler(.show) } func startCallRingtone() { guard let url = Bundle.main.url(forResource: "call_ringtone", withExtension: "mp3") else { return } do { audioPlayer = try AVAudioPlayer(contentsOf: url) audioPlayer?.play() // 45秒后自动停止 DispatchQueue.main.asyncAfter(deadline: .now() + 45) { if self.audioPlayer?.isPlaying == true { self.audioPlayer?.stop() self.audioPlayer = nil } } } catch { print(error.localizedDescription) } }
注意:iOS需在
Info.plist中添加UIBackgroundModes并包含audio,开启音频后台权限。
关键注意事项
- 权限:Android需确保应用拥有音频播放权限(使用资源文件无需额外权限,加载外部文件需
READ_EXTERNAL_STORAGE);iOS需开启音频后台权限。 - 交互同步:用户点击接听/拒接时,必须立即停止铃声播放,避免异常体验。
- 资源释放:播放结束或停止后,及时释放MediaPlayer/AVAudioPlayer资源,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Surajkaran Meghwanshi
相关产品推荐
相关产品推荐

