在静音模式下播放声音,应用程序终止状态

Posted

技术标签:

【中文标题】在静音模式下播放声音,应用程序终止状态【英文标题】:Playing sound in silent mode, app killed state 【发布时间】:2018-02-25 08:15:02 【问题描述】:

我需要在我的 ios 应用程序中收到推送通知时播放自定义声音。

我知道,苹果不支持静音模式下的声音提示。我试过用自定义声音发送推送通知。它在设备非静音时播放,并在静音模式下振动。

但是,最近我发现了一个应用程序 - Chipolo,它以静音模式显示自定义声音,即使应用程序处于终止状态。

播放声音提示使用什么技术?

非常感谢任何帮助!

【问题讨论】:

你找到解决办法了吗? 还没有。我联系了苹果寻求技术支持,关于这一点,他们的回答是设计的,应该是这样的。无法在静音模式和应用程序终止状态下播放声音。 Apple 的话 - “您描述的行为和由此产生的限制是设计使然。如果您认为 Apple 应该考虑替代方法,我们鼓励您提交增强请求,并提供有关此设计决策如何影响您以及您的内容的信息”希望看到不同的做法。” 但我想知道,像 Chipolo 这样的应用程序是如何做到的。不知道。 【参考方案1】:

我们无法在收到推送通知时更改系统声音,但我们可以使用MediaPlayerAVFoundation 播放音频。我们需要使用 Notification Service 扩展来处理前台和后台通知

在 NotificationService 扩展中

import UserNotifications
import AVFoundation
import MediaPlayer

class NotificationService: UNNotificationServiceExtension 


    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) 
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

        // Properties
        var error:NSError?
        var audioPlayer = AVAudioPlayer()

        let tempInfo = request.content.userInfo as! [String:NSObject]
        var songName = ""
        if tempInfo.index(forKey: "SoundFileName") != nil 
            songName = (tempInfo["SoundFileName"] as! String)
        

        var opecode = ""
        if tempInfo.index(forKey: "Opcode") != nil 
            opecode = (tempInfo["Opcode"] as! String)
        

        if opecode == "RingDevice" 
            var songTitle = ""
            var songExtension = ""
            if songName == "" 
                songTitle = "Input"
                songExtension = "caf"
             else  
                let testStr = songName.components(separatedBy: ".")
                songTitle = "\(testStr[0])"
                songExtension = "\(testStr[1])"
            

                if let url = Bundle.main.url(forResource: "\(songTitle)", withExtension: "\(songExtension)")  

                    let volumeView = MPVolumeView()
                    if let view = volumeView.subviews.first as? UISlider
                        view.value = 1.0 //---0 t0 1.0---

                    

                    do 
                        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)

                        try AVAudioSession.sharedInstance().setActive(true)

                        audioPlayer = try AVAudioPlayer(contentsOf: url,  fileTypeHint: AVFileType.caf.rawValue)
                        audioPlayer.volume = 1.0
                        DispatchQueue.main.asyncAfter(deadline: .now() + 5)  // Give 5 sec delay to play audio or else audio will not hearable
                             audioPlayer.play()
                        
                     catch _ as NSError 
                        print("[SoundPlayer] There was an error: \(String(describing: error))")
                    

                    if (audioPlayer.isPlaying) 
                        audioPlayer.stop()
                    
                    audioPlayer.play()
                
        


        if let bestAttemptContent = bestAttemptContent 
            // Modify the notification content here...            
            bestAttemptContent.title = "\(bestAttemptContent.title)"

            contentHandler(bestAttemptContent)
        
    

    override func serviceExtensionTimeWillExpire() 
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent 
            contentHandler(bestAttemptContent)
        
    


在我的情况下,我需要检查 pushnotification SoundFileNameOpcode 中的两个参数。如果OpcodeRingDevice 表示我正在播放PushNotification 中提到的声音

别忘了开启后台模式

希望对你有帮助:)

【讨论】:

谢谢你。我已经尝试过这种方法。但是当应用程序处于终止状态并且手机处于静音模式时,它没有播放音频。当使用主页按钮最小化应用程序时,我能够在 backgroud.ie 中播放音频 它在 Killed 状态下为我工作。你开启后台模式了吗?回答更新检查一次【参考方案2】:

至于在设备处于静音模式时播放声音,您根本无法立即进行。 只有 Apple 可以在寻找设备等紧急情况下覆盖静音开关。您的应用也需要Apple 的特别许可

Ganesh 的回答是没有它你能做的最好的事情。

【讨论】:

以上是关于在静音模式下播放声音,应用程序终止状态的主要内容,如果未能解决你的问题,请参考以下文章

静音模式下的 UILocalNotification 声音

应用程序处于后台且静音模式开启时需要播放声音

iphone,即使在静音或静音模式下如何播放声音?

iOS响铃/静音开关设置为静音模式时没有声音

即使 iPhone 处于静音状态,AVAudioPlayer 仍在播放环境声音

iPhone处于静音模式时不播放声音