iphone - iOS - 尝试播放 mp3 文件失败

标签 iphone ios ipad audio avaudioplayer

我正在尝试通过我的应用执行以下操作来播放我从服务器检索到的 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.)"

没有其他迹象表明它只是失败了,有什么想法吗?

更新:根据 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

更新:我遇到的真正问题是没有创建 AVAudioSession 实例并将 AVAudioSession 实例设置为在我的代码中播放,这样做以及我接受的更正答案使它起作用。

最佳答案

我发现您的代码至少有一个问题,即

NSURL *fileURL = [NSURL URLWithString:filePath];

它尝试创建一个带有本地文件路径的 URL。它可能会返回零。您应该改用:

NSURL *fileURL = [NSURL fileURLWithPath:filePath];

现在,即使这样,您的代码也无法运行(我试过了,得到了与您相同的错误)。我自己没有使用过 AVAudioPlayer 所以我不知道为什么会出现你的具体错误。

但是,我确实使用您的代码尝试了一个非常小的示例,并且能够正确播放 MP3。您可以使用 AVAudioPlayer 的 initWithData 构造函数,而不是将数据下载到文件并从文件加载 AVAudioPlayer:

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,但你不要将 View 附加到你的 View 层次结构中。这样,您将只有音频,不会改变应用程序的任何视觉效果。

一个例子是:

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

关于iphone - iOS - 尝试播放 mp3 文件失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10195410/

相关文章:

iphone - 什么是 GPX 文件以及它的用途是什么?

ios - JSQMessagesViewController:如何在 viewDidLoad 中获取 senderId?

objective-c - 关于捕获视频截图的问题

c# - Monotouch IPA 替换在同一台计算机上签名的另一个应用程序

应用程序中的 iPhone 应用程序商店 url

iphone - 为什么我会收到此错误 "error: expected specifier-qualifier-list before ' NSManagedObjectContext'?

ios - 检查 Swift 中两个字符串表达式之间的相似性

iphone - CGContextAddEllipseInRect 到 CGImageRef 到 CGImageMaskCreate 到 CGContextClipToMask

iphone - UITextField 移动时键盘将阻止它

ios - 如何在 objective-c 中按下条形按钮时隐藏键盘