ios nstimer run in background for check alarm time

2019-01-26 02:24发布

I googled it for hours, but could not find any information if there is any way to keep a running NSTimer active when the app is running in the background ? Please Help me , when app is go to background then one function run and each sec check alarm time is equal to current time , then play audio and open close alarm page If anybody know alarm app open source and its run on background please share with me Here i try this , but this is not working

- (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";

                }
            }

        }
    }


}

Please help me,

3条回答
We Are One
2楼-- · 2019-01-26 03:05

Please note that Apple will certainly reject any app that abuses their backgrounding policy so doing so would only be useful for personal and enterprise uses!

So how are we going to abuse the iOS background policy? We are going to declare our app as a background music player but not play any music.

1) First make sure your app has, in Capabilities -> Background Modes turned on and “Audio and AirPlay” enabled. Also make sure you’re import AVFoundation

2) Now create your silent music file. I had success with a one-second MP3 file of silence. The audio file does not have to be silent, but why scare the user with a random audio file? Add this to the “Supporting Files” category.

3) Add a property to the View Controller that will hold the silent audio player.

Swift:   
   var player = AVPlayer()

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

4) Now, you should set up the audio session. I chose to do this in viewDidLoad of my view controller of the single view in the demo app.

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];

The category AVAudioSessionCategoryPlayback is one of the few categories that allow for backgrounding. The option AVAudioSessionCategoryOptionMixWithOthers will make sure your silent audio won’t stop any currently playing background audio and also make sure that when the user plays music in the future, it won’t kick off your background task. A good developer will also check the return values and sessionError, but I’m not a good developer.

5) Now create the actual player item for your silent audio file. If you are embedding your audio file a different way, feel free to adapt this to do so. No trickery here.

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) HERE’S THE TRICK! This makes sure that the audio player is kept active after playing your sound file. The alternative is to keep looping a silent track, but why waste more CPU cycles (and battery)?

Swift:
   player.actionAtItemEnd = .None

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

7) Now, whenever you wish to keep the app in the background, just call

Swift:
   player.play()

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

And your app will keep working even after the user switches the app.

查看更多
可以哭但决不认输i
3楼-- · 2019-01-26 03:06

Scheduling local notification will do that you want.Use Calendar and date components for firing local notification on today at specific time or on some other date at specific time here you go

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;

if you check it in simulator then it will print TimeZone free Date/time value. Don't worry the notification will be fired with local timezone of device.

查看更多
贪生不怕死
4楼-- · 2019-01-26 03:19

NSTimer will not run in background. and using beginBackgroundTaskWithExpirationHandler won't save your problem. with background task your app can run max 10 min and then will get killed

you should use UILocalNotification

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

calculate time with NSCalendar and add this line:

localNotification.repeatInterval = NSDayCalendarUnit;
查看更多
登录 后发表回答