14

So, I'm trying to figure out how to monitor the battery level and state changes in iOS devices.

So far I've determined how to get the current battery level, but can't figure out how to get the state or how to monitor any changes so I can pop a dialog (or notification, but I assume I can't monitor this in the background anyway so...) when 100% charged.

This is what I have so far:

@IBOutlet var BatteryLevelLabel: UILabel!
@IBOutlet var BatteryStateLabel: UILabel!

// function to return the devices battery level
    func batteryLevel()-> Float {
        return UIDevice.currentDevice().batteryLevel
    }

// function to return the devices battery state (Unknown, Unplugged, Charging, or Full)
    func batteryState()-> UIDeviceBatteryState {
        return UIDevice.currentDevice().batteryState
    }

override func viewDidLoad() {
        super.viewDidLoad()

         let currentBatteryLevel = batteryLevel()

        // enables the tracking of the devices battery level
        UIDevice.currentDevice().batteryMonitoringEnabled = true

        // shows the battery level on labels
        BatteryLevelLabel.text = "\(batteryLevel() * 100)%)"
        BatteryStateLabel.text = "\(batteryState())"
        print("Device Battery Level is: \(batteryLevel()) and the state is \(batteryState())")

// shows alert when battery is 100% (1.0)
        if currentBatteryLevel == 1.0{
            let chargedAlert = UIAlertController(title: "Battery Charged", message: "Your battery is 100% charged.", preferredStyle: UIAlertControllerStyle.Alert)

            chargedAlert.addAction(UIAlertAction(title: "Ok", style: .Default, handler: { (action: UIAlertAction!) in
                print("Handle Ok logic here")
            }))
            presentViewController(chargedAlert, animated: true, completion: nil)
        }

    }

Any assistance here would be greatly appreciated! Thanks!

jammyman34
  • 1,399
  • 4
  • 15
  • 22

4 Answers4

25

You can use the battery state notification UIDeviceBatteryStateDidChangeNotification and UIDeviceBatteryLevelDidChangeNotification to be notified when its state changed:

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "batteryStateDidChange:", name: UIDeviceBatteryStateDidChangeNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "batteryLevelDidChange:", name: UIDeviceBatteryLevelDidChangeNotification, object: nil)   

    // Stuff...
}

func batteryStateDidChange(notification: NSNotification){     
    // The stage did change: plugged, unplugged, full charge...
}

func batteryLevelDidChange(notification: NSNotification){     
   // The battery's level did change (98%, 99%, ...)
}
tbaranes
  • 3,560
  • 1
  • 23
  • 31
  • There's a corresponding notification for the state change: `UIDeviceBatteryStateDidChangeNotification` – Aaron Brager Jul 13 '15 at 19:07
  • hmm, so I added the NSNotificationCenter line to my viewDidLoad() and added the batteryStateDidChange function. Then copied my BatteryLevelLabel.text = "\(batteryLevel() * 100)%" to this new func (assuming it would change as the battery charged) and put the alert code in there as well. Ran the app on my device, which was charged at 98%, kept it plugged in. Charged to 99%, the label didn't update. Charged to 100% the alert was not triggered. Obviously I'm doing something wrong? – jammyman34 Jul 13 '15 at 20:30
  • 1
    This notification will be fired only when the state changed which means not for each percent consumed or gain back, but to say unplugged, charging, full... if you want to be notified for each percent, replace `UIDeviceBatteryStateDidChangeNotification` by `UIDeviceBatteryLevelDidChangeNotification` – tbaranes Jul 14 '15 at 09:45
  • Yep, that was it! Thank you so very much! – jammyman34 Jul 14 '15 at 22:49
  • 3
    'UIDevice.currentDevice().batteryMonitoringEnabled = true'
    should be Before adding Observer. In swift 2 i got notification triggered only after adding above line
    – ak2g Dec 07 '15 at 16:02
  • You'll want to add code inside your handliers like: `if (UIDevice.current.batteryState == UIDeviceBatteryState.unplugged) ...` – Brad Mar 18 '18 at 15:32
  • I'm just getting around to the Battery State bit and I can't get it to work at all. Battery Level works great though. I've got a function to return the batteries state: func batteryState()-> UIDevice.BatteryState { return UIDevice.current.batteryState } I've got monitoring enabled in my viewDidLoad, I've got battery state changes being tracked: otificationCenter.default.addObserver(self, selector: Selector(("batteryStateDidChange:")), name: UIDevice.batteryStateDidChangeNotification, object: nil) and I've got a function for batteryStateDidChange, but the state won't print. – jammyman34 Feb 12 '19 at 18:29
  • I had to use `UIDevice.current` as the `object` argument of `addObserver:` to make it work. See this answer https://stackoverflow.com/a/48839291/987846 – kakyo Nov 29 '19 at 03:36
7

Here is the new way of implementing the code @tbaranes suggested for Swift 3.0

NotificationCenter.default.addObserver(self, selector: Selector(("batteryStateDidChange:")), name: NSNotification.Name.UIDeviceBatteryStateDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: Selector(("batteryLevelDidChange:")), name: NSNotification.Name.UIDeviceBatteryLevelDidChange, object: nil)
KSigWyatt
  • 1,368
  • 1
  • 16
  • 33
1

There are new methods now through the UIDevice class:

Getting the Device Battery State

var batteryLevel: Float

The battery charge level for the device.

var isBatteryMonitoringEnabled: Bool

A Boolean value indicating whether battery monitoring is enabled (true) or not (false).

var batteryState: UIDeviceBatteryState

The battery state for the device.

With UIDeviceBatteryState having the following values:

case unknown

The battery state for the device cannot be determined.

case unplugged

The device is not plugged into power; the battery is discharging.

case charging

The device is plugged into power and the battery is less than 100% charged.

case full

The device is plugged into power and the battery is 100% charged.

jlmurph
  • 1,050
  • 8
  • 17
0

Swift 5 Version of the solution:

NotificationCenter.default.addObserver(self, selector: #selector(batteryLavelChanged), name: UIDevice.batteryLevelDidChangeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(batteryStateChanged),name: UIDevice.batteryStateDidChangeNotification, object: nil)
Nazmul Hasan
  • 123
  • 6