X分钟后停止音频播放器

时间:2016-01-19 10:18:51

标签: ios objective-c iphone

我正在开发音频应用程序。我必须完成的一项任务是能够在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");
        }
    }];
}

它有效,但是,我不喜欢这最后一段代码。有没有更好的方法呢?

1 个答案:

答案 0 :(得分:0)

解决方案1。我已经实现了类似的东西,但不是你想要的东西。我做的是,当赛道结束时,检查睡眠时间,如果超过,则停止播放器,这是用玩家实现睡眠定时器的被动方式。也许,这个解决方案对你也有用吗?

解决方案2. 如果您的应用支持后台模式,即它在后台播放音频,您可以安排定时器(无需开始后台任务)在{{1}的准确时间内调用} initWithFireDate:的初始化方法。这样做,你的计时器不会每秒都被调用,而是在准确的时间。

希望这有用。祝你好运!

P.S。:请记住,两种解决方案都要求您的应用注册背景模式,至少是音频。