iOS 5 - AVAPlayer больше не работает
У меня есть немного кода, который работал нормально с iOS 4.3. Я заглянул в Интернет, я обнаружил, что у других была та же проблема без ответа, которая работала для меня. Я думаю, что могу что-то записать, но не могу сыграть. Вот мой код:
DetailViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>
#import <AudioToolbox/AudioServices.h>
@interface DetailViewController : UIViewController <UISplitViewControllerDelegate, AVAudioRecorderDelegate> {
id detailItem;
UILabel *detailDescriptionLabel;
IBOutlet UIButton *btnStart;
IBOutlet UIButton *btnPlay;
//Variables setup for access in the class:
NSURL * recordedTmpFile;
AVAudioRecorder * recorder;
BOOL toggle;
}
// Needed properties
@property (nonatomic, retain) IBOutlet UIButton *btnStart;
@property (nonatomic, retain) IBOutlet UIButton *btnPlay;
@property (strong, nonatomic) id detailItem;
@property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
-(IBAction) start_button_pressed;
-(IBAction) play_button_pressed;
@end
DetailViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
toggle = YES;
btnPlay.hidden = YES;
NSError *error;
// Create the Audio Session
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
// Set up the type of session
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
// Activate the session.
[audioSession setActive:YES error:&error];
[self configureView];
}
-(IBAction) start_button_pressed{
if (toggle) {
toggle = NO;
[btnStart setTitle:@"Press to stop recording" forState:UIControlStateNormal];
btnPlay.enabled = toggle;
btnPlay.hidden = !toggle;
NSError *error;
NSMutableDictionary *recordSettings = [[NSMutableDictionary alloc] init];
[recordSettings setValue:[NSNumber numberWithInt:kAudioFormatAppleIMA4] forKey:AVFormatIDKey];
[recordSettings setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[recordSettings setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
// Create a temporary files to save the recording.
recordedTmpFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat: @"%.0f.%@", [NSDate timeIntervalSinceReferenceDate] * 1000.0, @"caf"]]];
NSLog(@"The temporary file used is: %@", recordedTmpFile);
recorder = [[AVAudioRecorder alloc] initWithURL:recordedTmpFile settings:recordSettings error:&error];
[recorder setDelegate:self];
[recorder prepareToRecord];
[recorder record];
}
else {
toggle = YES;
[btnStart setTitle:@"Start recording" forState:UIControlStateNormal];
btnPlay.hidden = !toggle;
btnPlay.enabled = toggle;
NSLog(@"Recording stopped and saved in file: %@", recordedTmpFile);
[recorder stop];
}
}
-(IBAction) play_button_pressed{
NSError *error;
AVAudioPlayer * avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:recordedTmpFile error:&error];
if (!error)
{
[avPlayer prepareToPlay];
[avPlayer play];
NSLog(@"File is playing");
}
}
- (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) player
successfully: (BOOL) flag {
NSLog (@"audioPlayerDidFinishPlaying:successfully:");
}
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *) aRecorder successfully: (BOOL)flag
{
NSLog (@"audioRecorderDidFinishRecording:successfully:");
}
Вот моя программа работает:
2011-11-25 11: 58: 02.005 Bluetooth1 [897: 707] Используемый временный файл: file://localhost/private/var/mobile/Applications/D81023F8-C53D-4AC4-B1F7-14D66EB4844A/tmp/343915082005.caf 2011-11-25 11:58:05.956 Bluetooth1[897:707] Запись остановлена и сохранена в файле: file://localhost/private/var/mobile/Applications/D81023F8-C53D-4AC4-B1F7-14D66EB4844A/tmp/343915082005.caf 2011-11-25 11:58:05.998 Bluetooth1[897:707] audioRecorderDidFinish Запись: успешно: 2011-11-25 11:58:11.785 Bluetooth1[897:707] Файл воспроизводится
По какой-то причине функция audioPlayerDidFinishPlaying никогда не вызывается. Однако, похоже, что-то было записано. Сейчас я не знаю, какая часть не работает, но я думаю, это как-то связано с AVAudioPlayer.
[РЕДАКТИРОВАТЬ] Это становится все страннее и страннее. Я хотел убедиться, что что-то записано, поэтому я искал продолжительность записи. Вот новая функция воспроизведения:
-(IBAction) play_button_pressed{
NSError *error;
AVAudioPlayer * avPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: recordedTmpFile error:&error];
if (!error)
{
AVURLAsset* audioAsset = [AVURLAsset URLAssetWithURL:recordedTmpFile options:nil];
CMTime audioDuration = audioAsset.duration;
float audioDurationSeconds = CMTimeGetSeconds(audioDuration);
[avPlayer prepareToPlay];
[avPlayer play];
NSString *something = [NSString stringWithFormat:@"%f",audioDurationSeconds];
NSLog(@"File is playing: %@", something);
}
else
{
NSLog(@"Error playing.");
}
}
Теперь длина записи записана, и это имеет смысл (если я записываю в течение 10 секунд, это показывает что-то около 10 секунд). Однако, когда я поместил эти строки кода в первый раз, я забыл выполнить преобразование с плавающей точкой в NSString. Таким образом, он упал... и приложение воспроизводит звук... После различных тестов я могу сделать вывод, что мое приложение может записывать и воспроизводить звук, но при этом происходит сбой при воспроизведении записанного звука. Я понятия не имею, в чем может быть проблема. Я обнаружил, что AVPlayer является асинхронным, это как-то связано с этим? Я полностью потерян...
3 ответа
Хорошо, это не очень круто отвечать на ваши собственные вопросы. Более того, когда ответ не чистый, но он работает... Чтобы воспроизвести то, что я записал, я использовал следующий блок кода:
AVURLAsset* audioAsset = [AVURLAsset URLAssetWithURL:recordedTmpFile options:nil];
CMTime audioDuration = audioAsset.duration;
float audioDurationSeconds = CMTimeGetSeconds(audioDuration);
[avPlayer prepareToPlay];
[avPlayer play];
// Block for audioDurationSeconds seconds
[NSThread sleepForTimeInterval:audioDurationSeconds];
Я рассчитываю длину записанного файла и жду этого количества времени... он грязный, но делает свое дело. Плюс, если он запущен в другом потоке, он не будет блокировать приложение.
У кого-нибудь есть что-то, что я бы с радостью взял!
Замените urlpath следующим кодом:
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filepath = [documentsDirectory stringByAppendingPathComponent:@"urfile.xxx"];
NSURL *url = [NSURL fileURLWithPath:filepath];