Reputation: 1043
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
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
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:
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
Reputation: 4045
You need to set UIBackgroundModes
to audio in your application plist file.
Upvotes: 2