Getting Battery Health Information on iOS

ShayanK picture ShayanK · Mar 16, 2016 · Viewed 8.6k times · Source

There are currently apps in the app-store (so it does not require jailbreak) that tell you :

  1. Exact percentage value of battery level you have on your iPhone. I have tried Apple's official Code Sample, although it tells you when your iPhone is charging and discharging but it gives me values in 5% steps. How do these apps get exact values of battery percentage?

  2. Applications like Battery Health show

    • Current Maximum Capacity vs Manufacturer's Capacity
    • Current Discharge Rate
    • Lifetime Battery Cycle Count
  3. The same application also gives information about the Charging Rate in Watts when the phone is charging (check images) and current Charger's Power Rating.

Application: Battery Health screenshot 1 Application: Battery Health screenshot 2


How do these applications get so much detail about battery health when [UIDevice] provides so little information about it and almost no information on battery health and performance.

Answer

ldoogy picture ldoogy · Apr 29, 2016

I've developed a solution that will allow you to obtain this information without invoking any private API calls (though I certainly couldn't promise you Apple would approve it).

While the information in question does originate from IOKit, I've found a way of getting it without relying on IOKit. My solution relies on absolutely no private APIs of any kind. Instead, I developed a component called UIDeviceListener that effectively hijacks the IOKit data from UIDevice.

Give it a try, I've put together a simple sample program: https://github.com/eldoogy/PowerData

As an example, here is what the IOKit dictionary it retrieves tends to look like (note that it can vary by iOS versions and by device model, generation, etc.):

{
    AdapterDetails =     {
        Amperage = 1000;
        Description = "usb host";
        FamilyCode = "-536854528";
        PMUConfiguration = 1000;
        Watts = 5;
    };
    AdapterInfo = 16384;
    Amperage = 1000;
    AppleRawCurrentCapacity = 1279;
    AppleRawMaxCapacity = 1275;
    AtCriticalLevel = 0;
    AtWarnLevel = 0;
    BatteryData =     {
        BatterySerialNumber = REDACTED;
        ChemID = 355;
        CycleCount = 524;
        DesignCapacity = 1420;
        Flags = 640;
        FullAvailableCapacity = 1325;
        ManufactureDate = REDACTED;
        MaxCapacity = 1273;
        MfgData = REDACTED;
        QmaxCell0 = 1350;
        StateOfCharge = 100;
        Voltage = 4194;
    };
    BatteryInstalled = 1;
    BatteryKey = "0003-default";
    BootBBCapacity = 52;
    BootCapacityEstimate = 2;
    BootVoltage = 3518;
    CFBundleIdentifier = "com.apple.driver.AppleD1815PMU";
    ChargerConfiguration = 990;
    CurrentCapacity = 1275;
    CycleCount = 524;
    DesignCapacity = 1420;
    ExternalChargeCapable = 1;
    ExternalConnected = 1;
    FullyCharged = 1;
    IOClass = AppleD1815PMUPowerSource;
    IOFunctionParent64000000 = <>;
    IOGeneralInterest = "IOCommand is not serializable";
    IOInterruptControllers =     (
        IOInterruptController34000000,
        IOInterruptController34000000,
        IOInterruptController34000000,
        IOInterruptController34000000
    );
    IOInterruptSpecifiers =     (
        <03000000>,
        <26000000>,
        <04000000>,
        <24000000>
    );
    IOMatchCategory = AppleD1815PMUPowerSource;
    IOPowerManagement =     {
        CurrentPowerState = 2;
        DevicePowerState = 2;
        MaxPowerState = 2;
    };
    IOProbeScore = 0;
    IOProviderClass = AppleD1815PMU;
    InstantAmperage = 0;
    IsCharging = 0;
    Location = 0;
    Manufacturer = A;
    MaxCapacity = 1275;
    Model = "0003-A";
    Serial = REDACTED;
    Temperature = 2590;
    TimeRemaining = 0;
    UpdateTime = 1461830702;
    Voltage = 4182;
    "battery-data" =     {
        "0003-default" = <...>;
        "0004-default" = <...>;
        "0005-default" = <...};
    "built-in" = 1;
}