ios nstimer запускается в фоновом режиме для проверки времени будильника, равного текущему времени, и воспроизведения звука

Я искал его в течение нескольких часов, но не смог найти никакой информации, есть ли способ сохранить работающий NSTimer активным, когда приложение работает в фоновом режиме? Пожалуйста, помогите мне, когда приложение переходит в фоновый режим, тогда запускается одна функция, и каждая секунда проверяет время будильника, равное текущему времени, затем воспроизводит звук и открывается закрытая страница будильника. Если кто-нибудь знает приложение для будильника с открытым исходным кодом и его запуск в фоновом режиме, поделитесь со мной Вот я пробую это, но это не работает

- (void)applicationDidEnterBackground:(UIApplication *)application
{

    inBackground=YES;
    UIApplication*    app = [UIApplication sharedApplication];

    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];

    // Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        while (inBackground == YES) {


            [NSTimer scheduledTimerWithTimeInterval:1.0 target:self
                                          selector:@selector(checkAlert) userInfo:nil repeats:YES];

        }


        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    });

}
-(void)checkAlert
{
    NSLog(@"Chalaaaaaa");
    NSString *checkAlarmOnOff = [defaults stringForKey:@"setAlarm"];
    // Switch Alarm From Setting page
    NSString *SwitchAlarm=[defaults stringForKey:@"setSwitchAlarm"];

    if([SwitchAlarm isEqualToString:@"ON"])
    {
        if([checkAlarmOnOff isEqualToString:@"YES"])
        {
            if(![alarmRun isEqualToString:@"Yes"])
            {

                NSString *getAlarmTime = [defaults stringForKey:@"setAlarmTime"];
                 NSLog(@"AA-%@",getAlarmTime);
                 NSLog(@"BB-%@",globalClockTime);
                if([getAlarmTime isEqualToString:globalClockTime])
                {
                    [self MusicAction];

                    [_audioPlayer play];
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alarm" message:@"Alarm On" delegate:self cancelButtonTitle:@"Off" otherButtonTitles:nil, nil];
                    [alert show];
                    alarmRun=@"Yes";

                }
            }

        }
    }


}

Помогите, пожалуйста,


person Nishant Chandwani    schedule 20.08.2014    source источник
comment
if ([getAlarmTime isEqualToString: globalClockTime]) кажется проблематичным. нет гарантии, что время будет равным. Попытайтесь создать отношения, если они больше, чем отношения.   -  person Serguei Fedorov    schedule 20.08.2014


Ответы (3)


NSTimer не будет работать в фоновом режиме. и использование beginBackgroundTaskWithExpirationHandler не спасет вашу проблему. с фоновой задачей ваше приложение может работать максимум 10 минут, а затем будет убито

вы должны использовать UILocalNotification

UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = dateTime;
localNotification.alertBody = [NSString stringWithFormat:@"Alert Fired at %@", dateTime];
localNotification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];

рассчитать время с помощью NSCalendar и добавить эту строку:

localNotification.repeatInterval = NSDayCalendarUnit;
person Hashmat Khalil    schedule 20.08.2014
comment
Спасибо, но одна проблема в том, что в моем приложении у меня есть только время для будильника, нет даты, что мне делать, пожалуйста, помогите мне. - person Nishant Chandwani; 20.08.2014

Планирование локального уведомления сделает то, что вы хотите. Используйте компоненты календаря и даты, чтобы активировать локальное уведомление сегодня в определенное время или в другую дату в определенное время.

NSCalendar *calendar = [NSCalendar currentCalendar];

    // Split the date into components but only take the year, month and day and leave the rest behind
    NSDateComponents *dateComponents = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:[NSDate date]]; // Current Date

    // Build the date formatter
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"h:mm a"];
    // Convert the string time into an NSDate
    NSDate *time = [formatter dateFromString:@"1:59 PM"]; //your hour:minutes am/pm values

    // Split this one in components as well but take the time part this time
    NSDateComponents *timeComponents = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | NSMinuteCalendarUnit ) fromDate:time];

    // Do some merging between the two date components
    dateComponents.hour = timeComponents.hour;
    dateComponents.minute = timeComponents.minute;

    // Extract the NSDate object again
    NSDate *fireTime = [calendar dateFromComponents:dateComponents];

    NSLog(@"Fire Time is  FireTime %@", fireTime);
     localNotification.fireDate = fireTime;

если вы проверите его в симуляторе, он напечатает значение даты / времени без временной зоны. Не волнуйтесь, уведомление будет запущено с местным часовым поясом устройства.

person Muhammad Adnan    schedule 20.08.2014

Обратите внимание, что Apple обязательно отклонит любое приложение, которое злоупотребляет их политикой фонового управления, поэтому это будет полезно только для личного и корпоративного использования!

Итак, как мы собираемся злоупотреблять фоновой политикой iOS? Мы собираемся объявить наше приложение проигрывателем фоновой музыки, но не будем воспроизводить музыку.

1) Сначала убедитесь, что в вашем приложении включены функции «Возможности» -> «Фоновые режимы» и «Аудио и AirPlay». Также убедитесь, что вы импортируете AVFoundation

2) Теперь создайте музыкальный файл без звука. Я добился успеха с односекундным файлом молчания в формате MP3. Звуковой файл не обязательно должен быть беззвучным, но зачем пугать пользователя случайным звуковым файлом? Добавьте это в категорию «Вспомогательные файлы».

3) Добавьте свойство к контроллеру представления, которое будет удерживать беззвучный аудиоплеер.

Swift:   
   var player = AVPlayer()

Obj-c:
   @property (nonatomic, strong) AVPlayer *player;

4) Теперь вам нужно настроить аудиосеанс. Я решил сделать это в viewDidLoad моего контроллера представления единственного представления в демонстрационном приложении.

Swift:
   do {
      try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, withOptions: .MixWithOthers)
      try AVAudioSession.sharedInstance().setActive(true)
   } catch {
      print(error)
   }

Obj-c:
   NSError *sessionError = nil;
   [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&sessionError];

Категория AVAudioSessionCategoryPlayback - одна из немногих категорий, которые позволяют использовать фон. Параметр AVAudioSessionCategoryOptionMixWithOthers гарантирует, что ваш беззвучный звук не остановит воспроизведение текущего фонового звука, а также гарантирует, что, когда пользователь будет воспроизводить музыку в будущем, он не запустит вашу фоновую задачу. Хороший разработчик также проверит возвращаемые значения и ошибку sessionError, но я плохой разработчик.

5) Теперь создайте собственно проигрыватель для вашего беззвучного аудиофайла. Если вы вставляете свой аудиофайл другим способом, не стесняйтесь адаптировать его для этого. Никаких уловок.

Swift:
   let path = NSBundle.mainBundle().pathForResource("30sec", ofType: "mp3")
   let item = AVPlayerItem(URL: NSURL(fileURLWithPath: path!))
   player = AVPlayer(playerItem: item)

Obj-c:
   AVPlayerItem *item = [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@”silence” withExtension:@”mp3″]];
   [self setPlayer:[[AVPlayer alloc] initWithPlayerItem:item]];

6) ВОТ УЛОВКА! Это гарантирует, что аудиоплеер остается активным после воспроизведения звукового файла. Альтернатива - продолжать зацикливать бесшумную дорожку, но зачем тратить больше циклов процессора (и батареи)?

Swift:
   player.actionAtItemEnd = .None

Obj-c:
   [[self player] setActionAtItemEnd:AVPlayerActionAtItemEndNone];

7) Теперь, когда вы хотите, чтобы приложение работало в фоновом режиме, просто позвоните

Swift:
   player.play()

Obj-c:
   [[self player] play];

И ваше приложение будет продолжать работать даже после того, как пользователь переключит приложение.

person d-link13    schedule 06.07.2016