2012-04-17 91 views
2

我试图播放和MP3文件,我从我的服务器检索我的应用程序执行以下操作:iOS的 - 在尝试播放MP3文件失败

- (IBAction)play:(UIButton *)sender { 
    dispatch_queue_t downloadQueue = dispatch_queue_create("audio data downloader", NULL); 
    dispatch_async(downloadQueue, ^{ 
     NSURL *audioURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@/%@.mp3", FONYK_FILES_URL, [self.voicenote valueForKeyPath:@"Fonyker.fonykid"], [self.voicenote valueForKeyPath:@"Voicenote.vnid"]]]; 
     NSData *audioData = [NSData dataWithContentsOfURL:audioURL]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      NSError *error = nil; 
      AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithData:audioData error:&error]; 
      NSLog(@"%@", error); 
      audioPlayer.delegate = self; 
      [audioPlayer play]; 
     }); 
    }); 
} 

播放失败,意味着没有发出声音,我调试一步我的应用程序一步时得到这样的输出:

Catchpoint 2 (exception thrown).Single stepping until exit from function __cxa_throw, which has no line number information. 

当我的NSLog在模拟器中的错误此出现:

Error Domain=NSOSStatusErrorDomain Code=-50 "The operation couldn’t be completed. (OSStatus error -50.)" 

没有别的表明它只是失败,任何想法?

UPDATE:修改我的代码按J_D答案,并在模拟器得到这个:

Error loading /System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn: dlopen(/System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn, 262): Symbol not found: ___CFObjCIsCollectable 
    Referenced from: /System/Library/Frameworks/Security.framework/Versions/A/Security 
    Expected in: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation 
in /System/Library/Frameworks/Security.framework/Versions/A/Security 
2012-04-17 15:03:43.054 Fonyk[8238:15307] Error loading /System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn: dlopen(/System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn, 262): Symbol not found: ___CFObjCIsCollectable 
    Referenced from: /System/Library/Frameworks/Security.framework/Versions/A/Security 
    Expected in: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation 
in /System/Library/Frameworks/Security.framework/Versions/A/Security 

UPDATE:真正的问题我没有创建和AVAudioSession例如设置在我的代码回放,这样做与我接受的更正答案一起工作。

回答

5

我看到至少有一个问题与您的代码,用线

NSURL *fileURL = [NSURL URLWithString:filePath]; 

它试图用一个本地文件路径创建一个URL。它可能会返回零。你应该改用:

NSURL *fileURL = [NSURL fileURLWithPath:filePath]; 

现在,即使是这样,你的代码也不会运行(我试过了,得到了同样的错误)。我自己并没有使用过AVAudioPlayer,所以我不知道你为什么会发生特定的错误。

然而,我用你的代码尝试一个非常小的例子,我能正确播放MP3。相反,数据下载到文件,从文件加载AVAudioPlayer的,你可以使用AVAudioPlayer的initWithData构造:

AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithData:[NSData dataWithContentsOfURL:audioURL] error:&error]; 

这工作在我身边很好,假设audioURL是有效的。我指着一个MP4我为我的测试服务器上。

所以用这个initWithData重写你的代码给出:

- (IBAction)play:(UIButton *)sender { 
    dispatch_queue_t downloadQueue = dispatch_queue_create("audio data downloader", NULL); 
    dispatch_async(downloadQueue, ^{ 
     NSURL *audioURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@/%@.mp3", FONYK_FILES_URL, [self.voicenote valueForKeyPath:@"Fonyker.fonykid"], [self.voicenote valueForKeyPath:@"Voicenote.vnid"]]]; 
     NSData *audioData = [NSData dataWithContentsOfURL:audioURL]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      NSError *error = nil; 
      AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithData:audioData error:&error]; 
      NSLog(@"%@", error); 
      audioPlayer.delegate = self; 
      [audioPlayer play]; 
     }); 
    }); 
} 

正如最后一个音符:您正在下载您之前就开始播放整个文件,这可能需要一段时间,消耗了大量的堆(或存储如果你把它保存在一个文件)

如果要传输,你可以使用的MPMoviePlayerController,但你不重视视图到您的视图层次。这样,您将只拥有音频,并且不会更改应用程序的任何视觉效果。

一个例子是:

NSURL *audioURL = [NSURL URLWithString:@"MY_MP3_URL"]; 
MPMoviePlayerController* player = [[MPMoviePlayerController alloc] initWithContentURL:audioURL]; 
[player play]; 

同样,就在我身边,在模拟器,它工作正常。

不要忘记释放播放器。您也可以为代表注册重要通知。

详情点击这里:http://developer.apple.com/library/ios/#documentation/mediaplayer/reference/MPMoviePlayerController_Class/Reference/Reference.html

+0

谢谢,我会试试看。关于你最后的观察,任何想法如何我可以流文件? – 8vius 2012-04-17 18:04:28

+0

这样做,它停止在AVAudioPlayer实例化并打印出:Catchpoint 10(抛出异常)。单步执行,直到退出函数__cxa_throw, (没有行号信息)。如果我继续,它什么都不做。 – 8vius 2012-04-17 18:09:58

+0

我不知道为什么它能正常工作,然后我使用了与我的答案完全相同的代码,只是我使用了自己的URL。也许这与这个URL的内容有关。我也在模拟器5.0上进行测试。要回答关于流式传输的问题,请使用MPMoviePlayerController。我将添加另一个答案来获得一些可读代码。 – 2012-04-17 18:29:20

1

您正在某处收到EXC_BAD_ACCESS。我建议删除所有异步代码并查看发生了什么。实际上,就异步调用而言,我的思维过程有点困惑。

请注意,AVAudioPlayer仅适用于LOCAL文件。似乎你可能会设置它从服务器播放音频文件,这将无法正常工作。

另外,你为什么不尝试NSLog的错误变量?

+0

得到这个错误域= NSOSStatusErrorDomain代码= -43 “的操作无法完成(OSStatus错误-43)。”。不知道当地的文件交易。我会更新我的代码和我发现的问题。而且我没有在任何地方获得EXC_BAD_ACCESS,所以我不知道。看看。还有,你为什么会对我的思维过程感到困惑? – 8vius 2012-04-17 16:55:25

+0

我猜OP应该使用AVPlayer而不是AVAudioPlayer播放来自远程位置的流。 – 2012-04-17 16:59:48

+0

根据Michael的新信息修改了我的问题。 – 8vius 2012-04-17 17:10:16