iOS:如何在APP处于后台时让Timer应用程序播放自定义声音?

时间:2015-01-13 16:04:22

标签: ios audio timer background uilocalnotification

一般问题/申请背景/目的:

我有一个Timer应用程序,当App处于 BACKGROUND状态并且收到UILocalNotification时,我想播放自定义声音。

我利用 UILocalNotification 来触发计时器(这是应用程序无法在后台运行超过10分钟的过程的唯一方法。)

的问题:

  • 有没有办法播放不同的UILocalNotification声音?如果是这样我该怎么办? (换句话说:当应用程序收到UILocalNotification时,会播放自定义声音 - 声音不够大......我想获得正确的闹铃声)

这是我发送UILocalNotification时设置声音的方式:

_localNotif.soundName = UILocalNotificationDefaultSoundName;

然后我创建通知并发布。应用收到后,我会按以下方法处理(请阅读代码注释以获取更多信息):

- (void)application:(UIApplication *)application didReceiveLocalNotification: (UILocalNotification *)notification {
    NSLog(@"received notification");

    // Here I try to play a custom sound created in a custom object 
    // however the sound does NOT get played when the APP is in BACKGROUND mode (but I still see the NSLog message in console "received notification" 
    SoundManager* audio = [SoundManager sharedInstance];
    [audio playSound:Standard];
}

3 个答案:

答案 0 :(得分:0)

尝试更改行

_localNotif.soundName = UILocalNotificationDefaultSoundName;

对于这样的事情:

_localNotif.soundName = "customSoundFileName.customSoundFileExtension";

正如它在official docs中所述,您必须在应用程序的主包中指定声音资源的文件名。 我有一个工作示例,如果您需要,我可以与您分享。 祝你好运!

答案 1 :(得分:0)

在您触发本地通知的视图控制器中:

.h

#import <AVFoundation/AVFoundation.h>

@interface ViewController : UIViewController <AVAudioPlayerDelegate>

@property (nonatomic, strong) AVAudioPlayer *notificationSound;

如果本地通知在应用代理中进入后台,则您不必触发本地通知,无论是否在后台,本地通知都会触发。当应用有效时,didReceiveLocalNotification是您处理它的方式:来自docs here

  

当正在运行的应用收到本地通知时发送给代理。

.m

-(void)startTimer {
    timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(runTimerTasks:) userInfo:nil repeats:YES];
    [self fireLocalNotification];
}

-(void)fireLocalNotification {
 UILocalNotification *timerDoneNotification = [[UILocalNotification alloc] init];
 timerDoneNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:secondsLeft];
 timerDoneNotification.alertBody = @"Time Up!";
 timerDoneNotification.alertAction = @"OK";
 timerDoneNotification.timeZone = [NSTimeZone defaultTimeZone];
 timerDoneNotification.soundName = @"alarm.aif"; 
 [[UIApplication sharedApplication] scheduleLocalNotification:timerDoneNotification];
}

然后,如果你只是想在其他地方播放/停止声音,就像当应用处于活动状态时,secondsLeft为0,你可以按如下方式调用它:

[self playAlarm];

-(void)playAlarm {
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *filePath = [mainBundle pathForResource:@"alarm" ofType:@"aif"];
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
NSError *error = nil;
self.notificationSound = [[AVAudioPlayer alloc] initWithData:fileData error:&error];
self.notificationSound.numberOfLoops = -1;
[self.notificationSound play];
}

并阻止它:

[self.notificationSound stop]; 

对此不利的是UILocalNotification声音不能超过30秒,但它回答了手头的问题。


参考UILocalNotification Docs

兴趣点:

  

当系统发送本地通知时,可能会发生一些事情,具体取决于应用程序状态和通知类型。如果应用程序不在最前面并且可见,则系统会显示警报消息,对应用程序进行标记,并播放声音 - 通知中指定的任何内容。如果通知是警报并且用户点击操作按钮(或者,如果设备被锁定,则拖动打开操作滑块),应用程序被唤醒或启动。 (如果用户点击您使用additionalActions属性指定的其中一个自定义操作,则应用程序将被唤醒或启动到后台。)在其应用程序:didFinishLaunchingWithOptions:方法中,应用程序委托可以从启动选项字典中获取UILocalNotification对象使用UIApplicationLaunchOptionsLocalNotificationKey键。委托可以检查通知的属性,如果通知在其userInfo字典中包含自定义数据,则它可以访问该数据并相应地处理它。另一方面,如果本地通知仅标记应用程序图标,并且响应中的用户启动应用程序,则调用应用程序:didFinishLaunchingWithOptions:方法,但选项字典中不包含UILocalNotification对象。当用户选择自定义操作时,app delegate的应用程序:handleActionWithIdentifier:forLocalNotification:completionHandler:方法被调用来处理操作。

     

如果应用程序在系统发送通知时最重要且可见,则会调用应用程序委托的应用程序:didReceiveLocalNotification:来处理通知。使用提供的UILocalNotification对象中的信息来确定要采取的操作。当应用程序已经位于最前端时,系统不会显示任何警报,标记应用程序的图标或播放任何声音。

答案 2 :(得分:0)

UILocalNotification *notification = [UILocalNotification new];
notification.fireDate = [NSDate date]; //
notification.alertBody = @"This is custom alarm";
notification.soundName = @"YourCustomAudioFile.aiff";
[[UIApplication sharedApplication] scheduleLocalNotification:notification];

BUT

您的自定义音频文件必须符合两个条件:

  1. 音频长度小于30秒
  2. 音频文件格式应为:原始PCM或MA4,或uLaw或aLaw(wavaiffcaf文件容器)
  3. 所以,如果你有MP3自定义闹钟声音,你应该转换它... 以下是Apple文档(查找Preparing Custom Alert Sounds部分)link