Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting Battery Health Information on iOS

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.

like image 371
ShayanK Avatar asked Mar 15 '16 23:03

ShayanK


People also ask

How do I know if my iPhone battery needs replacing?

The quickest way to find out when to replace your iPhone battery is by checking Settings > Battery > Battery Health. This feature has been available since iOS 11.3 after Apple was criticized for secretly slowing down old iPhones that caused unexpected shutdowns due to failing batteries.

What is good Battery Health iOS?

Apple considers any iPhone with a battery capacity of 80% or above to be in optimal condition. In fact, Apple feels so strongly about battery health that its 1-year warranty covers any battery at 80% capacity or more. It's not unusual to see iPhones that, after one year, still have a battery capacity of 95% or above.


1 Answers

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;
}
like image 166
ldoogy Avatar answered Sep 21 '22 06:09

ldoogy