SBM
SBM

Reputation: 1043

Record voice in background(when i tapped home button) using AVAudioRecorder

I'm new in IOS development.I'm trying to record user voice in background using AVAudioRecorder but I add "audio" to UIBackgroundModes but this don't help. By the way, Everything works perfect in foreground.When in the background the timer works fine but voice is not recording. How can i record from microphone from background ? Is this possible?

Upvotes: 7

Views: 7691

Answers (3)

Himanshu Mahajan
Himanshu Mahajan

Reputation: 4799

Yes, recording and playing both are possible when app is running in background. First, You need to enable the background modes for your app, use below steps.

-- Select your project file in the Navigator of Xcode. Then, from the Capabilities section, switch on the Background Modes subsection. After the list of background modes is given to you, tick on the Audio & Airplay switch.

-- Use below code to record and play the audio in foreground and background state of app. Below code also record and play the audio if device is in silent mode or user locks the device.

import UIKit
import AVFoundation

extension String {

       func stringByAppendingPathComponent(path: String) -> String {

             let nsSt = self as NSString
             return nsSt.stringByAppendingPathComponent(path)
       }
}

class ViewController: UIViewController, AVAudioPlayerDelegate, AVAudioRecorderDelegate{

var audioPlayer : AVAudioPlayer!
var audioRecorder : AVAudioRecorder!

@IBOutlet var recordButton : UIButton!
@IBOutlet var playButton : UIButton!
@IBOutlet var stopButton : UIButton!

override func viewDidLoad() {
    super.viewDidLoad()

    self.recordButton.enabled = true
    self.playButton.enabled = false
    self.stopButton.enabled = false
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

//MARK: UIButton action methods

@IBAction func playButtonClicked(sender : AnyObject){

    let dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
    dispatch_async(dispatchQueue, {

        if let data = NSData(contentsOfFile: self.audioFilePath())
        {
            do{
                let session = AVAudioSession.sharedInstance()

                try session.setCategory(AVAudioSessionCategoryPlayback)
                try session.setActive(true)

                self.audioPlayer = try AVAudioPlayer(data: data)
                self.audioPlayer.delegate = self
                self.audioPlayer.prepareToPlay()
                self.audioPlayer.play()
            }
            catch{
                print("\(error)")
            }
        }
    });
}

@IBAction func stopButtonClicked(sender : AnyObject){

    if let player = self.audioPlayer{
        player.stop()
    }

    if let record = self.audioRecorder{

        record.stop()
    }

    let session = AVAudioSession.sharedInstance()
    do{
        try session.setActive(false)
    }
    catch{
        print("\(error)")
    }
}

@IBAction func recordButtonClicked(sender : AnyObject){

    let session = AVAudioSession.sharedInstance()

    do{
        try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
        try session.setActive(true)
        session.requestRecordPermission({ (allowed : Bool) -> Void in

            if allowed {
                self.startRecording()
            }
            else{
                print("We don't have request permission for recording.")
            }
        })
    }
    catch{
        print("\(error)")
    }
}

func startRecording(){

    self.playButton.enabled = false
    self.recordButton.enabled = false
    self.stopButton.enabled = true

    do{

        let fileURL = NSURL(string: self.audioFilePath())!
        self.audioRecorder = try AVAudioRecorder(URL: fileURL, settings: self.audioRecorderSettings() as! [String : AnyObject])

        if let recorder = self.audioRecorder{
            recorder.delegate = self

            if recorder.record() && recorder.prepareToRecord(){
                print("Audio recording started successfully")
            }
        }
    }
    catch{
        print("\(error)")
    }
}

func audioFilePath() -> String{

    let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0]
    let filePath = path.stringByAppendingPathComponent("test.caf") as String

    //let filePath = NSBundle.mainBundle().pathForResource("mySong", ofType: "mp3")!
    return filePath
}

func audioRecorderSettings() -> NSDictionary{

    let settings = [AVFormatIDKey : NSNumber(int: Int32(kAudioFormatMPEG4AAC)), AVSampleRateKey : NSNumber(float: Float(16000.0)), AVNumberOfChannelsKey : NSNumber(int: 1), AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Medium.rawValue))]

    return settings
}

//MARK: AVAudioPlayerDelegate methods

func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) {

    if flag == true{
        print("Player stops playing successfully")
    }
    else{
        print("Player interrupted")
    }

    self.recordButton.enabled = true
    self.playButton.enabled = false
    self.stopButton.enabled = false
}

//MARK: AVAudioRecorderDelegate methods

func audioRecorderDidFinishRecording(recorder: AVAudioRecorder, successfully flag: Bool) {

    if flag == true{
        print("Recording stops successfully")
    }
    else{
        print("Stopping recording failed")
    }

    self.playButton.enabled = true
    self.recordButton.enabled = false
    self.stopButton.enabled = false
}
}

Just copy this code and paste it in empty view controller swift file, create three buttons "Record", Stop", "Play" in xib file or in storyboard file, connect @IBOutlet and @IBAction. Test this code on real device because you need mic to record the audio. I had tested it against xCode 7 and iOS 9 and its working.

Upvotes: 5

SBotirov
SBotirov

Reputation: 14128

You can. Skype does this.

You presumably need to set <key>UIBackgroundModes</key><array><string>audio</string></array> in Info.plist, and you need to make sure that the audio session is active/running/whatever before you switch apps (the assumption is that you won't suddenly start recording/playing music/whatever when your app is in the background).

The docs say that "audio" lets you play audio in the background, but presumably this also applies to recording audio. If it doesn't work, there are a few things you could try:

  • Set both "voip" and "audio".
  • Play silence (this might be easiest to do with the Audio Queue API).

This material from here:iOS multitasking for an Audio Recording application

Extra material see this:he recording stops as soon as I press the "HOME" button Building Background-Aware Applications

Upvotes: 7

taffarel
taffarel

Reputation: 4045

You need to set UIBackgroundModes to audio in your application plist file.

Upvotes: 2

Related Questions