简体   繁体   中英

NSUrlRequest works in simulator but not on iphone

I have an app which records sound from microphone and then sends it to my website through NSUrlRequest. To test it, I added that audio is played from website so I can hear if it worked.
When I test it on simulator, everything works fine: audio is recorded and uploaded and I can hear it, but when I install it on my iPhone, I cannot hear anything and at my website, there is a corrupted audio file.

My TestNahravani.swift Code:

import UIKit
import AVFoundation

class TestNahravani: UIViewController, AVAudioRecorderDelegate, AVAudioPlayerDelegate {


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

var soundRecorder: AVAudioRecorder!
var soundPlayer:AVAudioPlayer?

let fileName = "demo.m4a"

override func viewDidLoad() {
    super.viewDidLoad()
    setupRecorder()
}

@IBAction func recordSound(sender: UIButton) {
    if (sender.titleLabel?.text == "Record"){
        soundRecorder.record()
        sender.setTitle("Stop", for: .normal)
        playButton.isEnabled = false
    } else {
        soundRecorder.stop()
        sender.setTitle("Record", for: .normal)
    }
}

@IBAction func playSound(sender: UIButton) {
    if (sender.titleLabel?.text == "Play"){
        recordButton.isEnabled = false
        sender.setTitle("Stop", for: .normal)
        preparePlayer()
    } else {
        soundPlayer?.stop()
        sender.setTitle("Play", for: .normal)
    }
}

// MARK:- AVRecorder Setup

func setupRecorder() {

    //set the settings for recorder

    let recordSettings = [AVSampleRateKey : NSNumber(value: Float(44100.0)),
                          AVNumberOfChannelsKey : NSNumber(value: 2),
                          AVEncoderAudioQualityKey : NSNumber(value: Int32(AVAudioQuality.max.rawValue)),
                          AVFormatIDKey : NSNumber(value: kAudioFormatMPEG4AAC)]
    var error: NSError?
    do {
        soundRecorder =  try AVAudioRecorder(url: getFileURL() as URL, settings: recordSettings)
    } catch let error1 as NSError {
        error = error1
        soundRecorder = nil
    }

    if let err = error {
        print("AVAudioRecorder error: \(err.localizedDescription)")
    } else {
        soundRecorder.delegate = self
        soundRecorder.prepareToRecord()
    }
}

// MARK:- Prepare AVPlayer

func preparePlayer() {
    var errorX: NSError?




        let dirPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        let docsDir: AnyObject=dirPaths[0] as AnyObject
        var recordedFilePath : String = docsDir.appendingPathComponent(fileName)
        let recordedFileURL = getFileURL()

        // "currentFilename", "recordedFilePath" and "recordedFileURL" are all global variables

        // This recording stored at "recordedFileURL" can be played back fine.

        let sendToPath = "http://www.kvetinac97.cz/jt.php"
        let sendToURL = NSURL(string: sendToPath)
        let recording: NSData! = NSData(contentsOf: recordedFileURL as URL)
    if recording == nil {
        recordedFilePath = "FailedUpload"
    }
        let boundary = "--------14737809831466499882746641449----"
        let contentType = "multipart/form-data;boundary=\(boundary)"

        let beginningBoundary = "--\(boundary)"
        let endingBoundary = "--\(boundary)--"

        let header = "Content-Disposition: form-data; name=\"\(fileName)\"; filename=\"\(recordedFilePath)\"\r\n"

        let body = NSMutableData()
        body.append(("\(beginningBoundary)\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
        body.append((header as NSString).data(using: String.Encoding.utf8.rawValue)!)
        body.append(("Content-Type: application/octet-stream\r\n\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
        body.append(recording! as Data) // adding the recording here
        body.append(("\r\n\(endingBoundary)\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)

        let request = NSMutableURLRequest()
        request.url = sendToURL! as URL
        request.httpMethod = "POST"
        request.addValue(contentType, forHTTPHeaderField: "Content-Type")
        request.addValue("multipart/form-data", forHTTPHeaderField: "Accept")
        request.httpBody = body as Data

        let session = URLSession.shared
        let task = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
            if let data = NSData(contentsOf: NSURL(string: "http://www.kvetinac97.cz/uploads/demo.m4a")! as URL) {
                do {
                    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
                    try AVAudioSession.sharedInstance().setActive(true)
                    self.soundPlayer = try AVAudioPlayer(data: data as Data, fileTypeHint: AVFileType.m4a.rawValue)
                    self.soundPlayer!.delegate = self
                    self.soundPlayer!.prepareToPlay()
                    self.soundPlayer!.volume = 1.0
                    self.soundPlayer!.play()
                } catch let error1 as NSError {
                    errorX = error1
                    self.soundPlayer = nil
                    print ("Chyba nejaka \(error1)")
                }
            }
            else {
                print ("Smulicka")
            }
        })
        task.resume()


}

func generateBoundaryString() -> String {
    return "Boundary-\(NSUUID().uuidString)"
}

// MARK:- File URL

func getCacheDirectory() -> String {

    let paths = NSSearchPathForDirectoriesInDomains(.cachesDirectory,.userDomainMask, true)

    return paths[0]
}

func getFileURL() -> NSURL {

    let path = getCacheDirectory().appending(fileName)

    let filePath = NSURL(fileURLWithPath: path)

    return filePath
}

// MARK:- AVAudioPlayer delegate methods

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    recordButton.isEnabled = true
    playButton.setTitle("Play", for: .normal)
}

// MARK:- AVAudioRecorder delegate methods

func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
    playButton.isEnabled = true
    recordButton.setTitle("Record", for: .normal)
}

// MARK:- didReceiveMemoryWarning

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

}

I figured out where my problem was

As it appears, iPhone simulator does not require AVAudioSession to be activated whilst real iPhone does.

So it can be fixed easily with adding

try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryRecord)
try AVAudioSession.sharedInstance().setActive(true)

before audioRecorder initialization.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM