eldade / UIDeviceListener

Obtain power information (battery health, charger details) for iOS without any private APIs.
GNU General Public License v3.0
240 stars 38 forks source link

iOS 10 #3

Open HungChun opened 8 years ago

HungChun commented 8 years ago

Hi, Is there have any solution on iOS 10?

mice007 commented 8 years ago

I've seen Battery Life app can dig up battery design capacity and voltage so it can calculate wear level on iOS10 betas but I did not figure out how it does that yet.

eldade commented 8 years ago

Are you not getting a dictionary at all on iOS 10? I played with it a couple of weeks ago and I think I was seeing a very small dictionary, but I believe it did have the MaximumCapacity key which is probably how Battery Life is reporting the wear level.

mice007 commented 8 years ago

Nope, I'm not getting anything back on iOS10 but did not dig into this yet deeply enough to see whats broken... I've made a quick empty project with your solution and nothing worked.. I guess I'll need to do some debug to see what is happening.

eldade commented 8 years ago

Yeah just looked at it and it's totally broken. I'm not sure this mechanism can be made to work on iOS 10 honestly, but I'll keep playing with it. As a side note, there is a new function in UIDeviceListener called _addBatteryPropertyForKey that's reading the data from the main IOKit dictionary and constructing this new, limited dictionary. It is possible that the original dictionary has the full data still available, but it would require the use of IOKit to get to it.

In a way, it almost looks like this approach was taken specifically to prevent this code from working. Considering how many battery apps in the App Store now rely on this code, that wouldn't surprise me...

HungChun commented 8 years ago

I have try to get the data from IOKit but the data is just like Battery life(Voltage, MaxCapacity, CurrentCapacity...), and it doesn't have "Design Capacity". So I think Battery life is write the design capacity data in code. This way still can get the wear level !

eldade commented 8 years ago

Well getting the data from IOKit is easy but Apple tends to reject apps that do that.

    mach_port_t iokitPort = 0;
    CFMutableDictionaryRef properties;
    IOMasterPort(0, &iokitPort);
    CFDictionaryRef serviceName = IOServiceNameMatching("AppleARMPMUCharger");

    io_service_t service = IOServiceGetMatchingService(iokitPort, serviceName);

    if (service == 0)
        return nil;

    kern_return_t status = IORegistryEntryCreateCFProperties(service,
                                                             &properties,
                                                             kCFAllocatorDefault,
                                                             kNilOptions);

    IOObjectRelease(service);

Now the properties dictionary contains all of the data.

HungChun commented 8 years ago

I just got these data, same as yours?

AdapterInfo = 16384; AtCriticalLevel = 0; CurrentCapacity = 1376; ExternalChargeCapable = 1; ExternalConnected = 1; FullyCharged = 0; IOClass = AppleARMPMUCharger; IsCharging = 1; MaxCapacity = 1600; Voltage = 4272;

eldade commented 8 years ago

Yep, that's the lame dictionary we get in iOS 10 unfortunately.

tahirmt commented 8 years ago

Is it possible for you to create a branch with IOKit? I know it wouldn't be accepted on the App Store but I don't need it to. I can't seem to figure out how to write the code myself.

eldade commented 8 years ago

Sure just added a separate project for that called EEIOKitListener that grabs the dictionary and notifies you whenever the data changes. I haven't tested it on iOS 10 but it should work with the limited dictionary. Grab it from https://github.com/eldoogy/EEIOKitListener.git

mice007 commented 8 years ago

About the side note... Where is this "_addBatteryPropertyForKey" ?

eldade commented 8 years ago

That's just one of the internal symbols inside UIKit in the UIDevice implementation.

If you type something like di --name _addBatteryPropertyForKey into lldb, you should see the disassembly listing for that function and see what it does. Note that these functions don't exist in the simulator, only on a physical device so you have to be connected to a physical device and be in a live debugging session on iOS 10 in order to see it (the specific program shouldn't matter, this is just a function from UIKit that'll be loaded for pretty much any iOS app).

mice007 commented 8 years ago

Thanks! So basically we only have access to those limited battery info through IOKit (as you using in EEIOKitListener). As I saw in the store there are apps which utilizing this data so probably Apple is not rejecting these apps (for now).

mice007 commented 8 years ago

I still cannot figure out how to get any battery data from iOS10 without using the IOKit... any luck with this guys?

shrikanth2002 commented 8 years ago

My Project is totally depending on Charging CycleCount and Design Capacity, Now it was broken from iOS 10.0 , My Project is on hold now., Do any one have solution for this.

eldade commented 7 years ago

Literally the only approach that still works for iOS 10 is reading the data off of USB, from a Mac or PC. That still works in iOS 10, which is why apps like coconut battery on the Mac can still get the data. On the device the data appears to be totally gone from IOKit. I have thousands of inbound emails from disappointed users. :-(

mice007 commented 7 years ago

Yeah too bad Apple did hide this info from us instead of implementing some API calls to legalize this. Anyway, I still don't understand how is possible to get that very limited data without IOKit Framework so the app won't get rejected from the Store.... I'm not seeing any battery details with your method :(

vincentpeng520 commented 7 years ago

i doubted why the battery Life APP can get voltage the maxcapacity ,and didn't rebjected by apple .now the customer see the APP,and he thought i also must get that datas .before i use IOKit and was rebjected by apple ,now my project is paused ,and the boss always let me solve it.anybody can give me advice

noBugyl commented 7 years ago

ios 10 . cant get any information. why ? use your demo run on iphone get this: 08:00:00 batteryDesignCapacity=0 batteryCycleCount=0 batteryMaximumCapacity=0 batteryHealth=1.000000 batteryRawBatteryLevel=1.000000 voltage=0.000000 isPluggedIn=0 isCharging=0 isFullyCharged=0 batteryTemperature=0.000000 adapterAmperage=0 adapterWattage=0 chargerConfiguration=0 chargingAmperage=0 dischargeAmperage=0 devicePowerConsumption=0.000000

barkofdelight commented 7 years ago

Just fought with this for a while before looking on this site for forums. D'oh!

Thanks for the coconutBattery pointer, that works well enough for me. I'm seeing my reported battery level (iPhone5s, 3+years old) drop suddenly in the middle of the day. For example, it might say 25% left one minute and then fall to 1% next time I look. Then I plug the phone in and it jumps back to 25%.

I'm perplexed as to why Apple doesn't think we need access to this kind of information. Maybe they think that drawing conclusions from battery data is more of an art than a science! ;)

Anyway, thanks for making this available.

mitchell-dream commented 6 years ago

Can it be used in iOS11? @eldade