3

我已经为我的问题寻找合适的答案,但到目前为止我没有发现任何帮助。我想记录环境中的分贝。如果超过特定阈值,应用程序应播放声音或歌曲文件。到目前为止一切正常,但我很难让应用程序在后台运行。我已经添加了属性“应用程序不在后台运行”并将其值设置为“否”。我读过应该将“external-accessory”元素添加到“必需的背景模式”中。我也添加了,但它仍然不起作用。我正在使用AVAudioRecorder录制声音和AVPlayer播放声音/音乐文件。首先,我使用了,MPMediaController iPodMusicPlayer但它与属性“必需的背景模式”一起引发了异常。

编辑:我在 iOS 6 中使用 xCode 4.5

编辑 2:当我将字符串 viop 添加到“必需的后台模式”时,它似乎在后台继续录制。但是在后台时它仍然不播放音乐文件。我也尝试添加“音频”值,但没有帮助。

编辑 3:我咨询了苹果开发者参考资料。看来您必须配置您的 AVAudioSession。有了它似乎可以工作(参考链接)。但是现在我在播放多个文件时遇到了麻烦,因为一旦第一首曲目播放完毕,应用程序就会再次进入暂停模式。据我所知,不可能用多个文件初始化 AVPlayer 或 AVAudioPlayer。我使用了委托方法 audioPlayerDidFinishPlaying:successfully: 来设置下一首曲目,但它不起作用。

编辑 4:好的,一种可能性是避免停止录音机,即移除 [record stop] 以便它甚至在播放音乐时录制声音。这是一个可行的解决方法,但我仍然欣赏任何其他(更好的)解决方案。不需要让记录器一直运行的解决方案。

相关代码:我在 viewDidLoad 方法中初始化所有内容:

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view.

    //[MPMusicPlayerController applicationMusicPlayer];

    NSURL *url = [NSURL fileURLWithPath:@"/dev/null"];

NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
                          [NSNumber numberWithFloat: 44100.0],                 AVSampleRateKey,
                          [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
                          [NSNumber numberWithInt: 1],                         AVNumberOfChannelsKey,
                          [NSNumber numberWithInt: AVAudioQualityMax],         AVEncoderAudioQualityKey,
                          nil];

NSError *error;

recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
lowPassResults = -120.0;
thresholdExceeded = NO;

if (recorder) {
    [recorder prepareToRecord];
    recorder.meteringEnabled = YES;
    [recorder record];
            levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.03 target: self selector: @selector(levelTimerCallback:) userInfo: nil repeats: YES];

    } else {
    NSString* errorDescription = [error description];
    NSLog(errorDescription);
    }
}

每 0.03 秒调用一次的 levelTimer 回调:

- (void)levelTimerCallback:(NSTimer *)timer {
//refreshes the average and peak power meters (the meter uses a logarithmic scale, with -160 being complete quiet and zero being maximum input
[recorder updateMeters];

const double ALPHA = 0.05;

float averagePowerForChannel = [recorder averagePowerForChannel:0]; 

    //adjust the referential
    averagePowerForChannel = averagePowerForChannel / 0.6;

    //converts the values 
    lowPassResults = ALPHA * averagePowerForChannel + (1.0 - ALPHA) * lowPassResults;   

    float db = lowPassResults + 120;
    db = db < 0? 0: db;

    if(db >= THRESHOLD)
    {
        [self playFile];
    }
}

最后是播放音乐文件的 playFile 方法:

- (void) playFile {

    NSString* title = @"(You came down) For a day";
    NSString* artist = @"Forge";
    NSMutableArray *songItemsArray = [[NSMutableArray alloc] init];


    MPMediaQuery *loadSongsQuery = [[MPMediaQuery alloc] init];

    MPMediaPropertyPredicate *artistPredicate = [MPMediaPropertyPredicate predicateWithValue:artist forProperty:MPMediaItemPropertyArtist];
    MPMediaPropertyPredicate *titlePredicate = [MPMediaPropertyPredicate predicateWithValue:title forProperty:MPMediaItemPropertyTitle];
    [loadSongsQuery addFilterPredicate:artistPredicate];
    [loadSongsQuery addFilterPredicate:titlePredicate];

    NSArray *itemsFromGenericQuery = [loadSongsQuery items]; 

    if([itemsFromGenericQuery count])
        [songItemsArray addObject: [itemsFromGenericQuery objectAtIndex:0]];


    if([songItemsArray count])
    {
        MPMediaItemCollection *collection = [[MPMediaItemCollection alloc] initWithItems:songItemsArray];


        if ([collection count]) {

            MPMediaItem* mpItem = [[collection items]objectAtIndex:0];
            NSURL* mediaUrl = [mpItem valueForProperty:MPMediaItemPropertyAssetURL];
            AVPlayerItem* item = [AVPlayerItem playerItemWithURL:mediaUrl];
            musicPlayer = [[AVPlayer alloc] initWithPlayerItem:item];

            [musicPlayer play];
        }
    }
}

有人可以帮我解决我的问题吗?我还错过了什么吗?

4

1 回答 1

1

尝试这个,

AppDelegate.m

- (void)applicationDidEnterBackground:(UIApplication *)application
{
   __block UIBackgroundTaskIdentifier task = 0;
   task=[application beginBackgroundTaskWithExpirationHandler:^{
   NSLog(@"Expiration handler called %f",[application backgroundTimeRemaining]);
   [application endBackgroundTask:task];
   task=UIBackgroundTaskInvalid;
   }];
}
于 2013-07-26T10:49:04.627 回答