我正在开发音频应用程序。我必须完成的一项任务是能够在X分钟(由用户定义)之后停止音频播放器,就像玩家睡觉一样。
为此,我使用本地通知。
这是我的自定义播放器中的代码:
- (void)configureSleepTimer:(NSUInteger)seconds {
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:seconds];
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.soundName = UILocalNotificationDefaultSoundName;
NSDictionary *userInfo = [NSDictionary dictionaryWithObjects:@[@"PlayerSleep"] forKeys:@[@"type"]];
localNotification.userInfo = userInfo;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
NSLog(@"Notification: %@", localNotification);
}
的AppDelegate:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
if ([[notification.userInfo valueForKey:@"type"] isEqualToString:@"PlayerSleep"]) {
Player *player = [Player sharedInstance];
[player stopPlayer];
}
}
上述代码的问题在于,当应用在后台运行时播放器不会停止。
要在后台运行此操作,我会检查应用程序何时进入后台模式并检查是否存在本地通知。如果存在,我会启动一秒钟的计时器,将通知消息时间与真实日期进行比较,以便在需要时停止播放器。
- (void)applicationDidEnterBackground:(UIApplication *)application {
__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
[application endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if ([[[UIApplication sharedApplication] scheduledLocalNotifications] count]) {
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(sleepPlayer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:t forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
}
});
}
- (void)sleepPlayer {
[[[UIApplication sharedApplication] scheduledLocalNotifications] enumerateObjectsUsingBlock:^(UILocalNotification *notification, NSUInteger idx, BOOL *stop) {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"dd-MM-yyyy HH:mm:ss"];
NSString *dateTimeStr = [formatter stringFromDate:[NSDate date]];
NSString *notifDateStr = [formatter stringFromDate:[NSDate dateWithTimeInterval:-1 sinceDate:notification.fireDate]];
if ([dateTimeStr isEqualToString:notifDateStr]) {
Player *player = [Player sharedInstance];
[player stopPlayer];
[[UIApplication sharedApplication] cancelLocalNotification:notification];
NSLog(@"************************** Player Sleeped");
}
}];
}
它有效,但是,我不喜欢这最后一段代码。有没有更好的方法呢?
答案 0 :(得分:0)
解决方案1。我已经实现了类似的东西,但不是你想要的东西。我做的是,当赛道结束时,检查睡眠时间,如果超过,则停止播放器,这是用玩家实现睡眠定时器的被动方式。也许,这个解决方案对你也有用吗?
解决方案2. 如果您的应用支持后台模式,即它在后台播放音频,您可以安排定时器(无需开始后台任务)在{{1}的准确时间内调用} initWithFireDate:
的初始化方法。这样做,你的计时器不会每秒都被调用,而是在准确的时间。
希望这有用。祝你好运!
P.S。:请记住,两种解决方案都要求您的应用注册背景模式,至少是音频。