UIDeviceBatteryLevelDidChangeNotification issue when app goes in background

373 views Asked by At

I want to ring an alarm when the batterlevel reaches to 100 % (for testing i set it 11% or more) and the charger is not removed.

It works okay when the app is in foreground but stops when the app reaches to background.

Can anybody help please.

My code is as below for the viewcontroller.

    //
//  MainViewController.m
//  GoGreen
//
//  Created by nbtmac on 25/05/15.
//  
//

#import "MainViewController.h"


@interface MainViewController ()
{
    int timerCount;
    float batteryLevel;
    NSString *userID;
    NSDate *chargedAt;
    NSInteger chargedHr;
    NSInteger chargedMin;
    NSTimer* alarmTimer;
    SystemSoundID _soundId;
}

@end

@implementation MainViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self.tabBarController.tabBar setHidden:false];


    [self createSoundId];


}




- (void) viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];
    [self.tabBarController.tabBar setHidden:false];
    self.navigationItem.hidesBackButton = true;

    [UIDevice currentDevice].batteryMonitoringEnabled = YES;


    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(batteryLevelChanged:)
                                                 name:UIDeviceBatteryLevelDidChangeNotification object:nil];


    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(batteryStateChanged:)
                                                 name:UIDeviceBatteryStateDidChangeNotification object:nil];


}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

#pragma mark - Misc Methods




- (void) createSoundId
{
    NSString *soundPath = [[NSBundle mainBundle] pathForResource:@"Loud_Alarm_Clock_Buzzer" ofType:@"wav"];
    if ([[NSFileManager defaultManager] fileExistsAtPath:soundPath])
    {
        NSURL* soundPathURL = [NSURL fileURLWithPath:soundPath];
        AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundPathURL, &_soundId);
    }
}

-(void) alarmTimer:(NSTimer*) alarmTimer
{

    timerCount++;

    AudioServicesPlaySystemSound(_soundId);

}


- (void)batteryLevelChanged:(NSNotification *)notification
{
    batteryLevel = (([UIDevice currentDevice].batteryLevel) * 100);
    if (batteryLevel >= 11.00)
    {

        NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:[NSDate date]];
        chargedHr = [components hour];
        chargedMin = [components minute];

        if (timerCount < 1)
        {

        alarmTimer = [NSTimer scheduledTimerWithTimeInterval: 60.0 * 1 target: self
                                                          selector: @selector(alarmTimer:) userInfo: nil repeats: YES];
        }
        [UIApplication sharedApplication].idleTimerDisabled = YES;
    }

}

- (void)batteryStateChanged:(NSNotification *)notification
{


    UIDeviceBatteryState currentState = [UIDevice currentDevice].batteryState;
    if (currentState == UIDeviceBatteryStateFull)
    {

    }
    else if (currentState == UIDeviceBatteryStateUnplugged)
        {
            [alarmTimer invalidate];
            [UIApplication sharedApplication].idleTimerDisabled = NO;


            batteryLevel = (([UIDevice currentDevice].batteryLevel) * 100);
            NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:[NSDate date]];
            NSInteger unPlugHr = [components hour];
            NSInteger unPlugMin = [components minute];
            NSInteger totUnPlugMins = (unPlugHr * 60) + unPlugMin;
            NSInteger totChargedMins = (chargedHr * 60) + chargedMin + 1;



            if ((batteryLevel >= 100.00) && (totChargedMins > totUnPlugMins))
            {
                if(appDelegate().isInternetReachable)
                {




                }
                else
                {
                    [[Util okAlert:@"Error" message:@"Please check your internet connection."] show];

                }
            }
        }

}





@end

Thanks

Nirav

1

There are 1 answers

2
Robert J. Clegg On

When your app enters into background mode - almost all of your code is suspended. You'll need to do extra work for this to work using UILocalNotifications or something similar to get notified about future events while app remains in background.