2

我正在尝试从我的应用程序中从我的服务器检索播放和 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 实例设置为播放,这样做与我接受的更正答案一起使它工作。

4

2 回答 2

5

我发现您的代码至少有一个问题,如下所示

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

一个例子是:

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

于 2012-04-17T17:47:57.903 回答
1

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

请注意,AVAudioPlayer 仅适用于 LOCAL 文件。似乎您可能正在将其设置为播放来自服务器的音频文件,但这是行不通的。

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

于 2012-04-17T16:51:15.243 回答