由于项目需要,要求获取iOS手机电池电量的详细值以及变化量等信息。所以做了相关的技术调研,实现的方法有很多。所以写了这篇总结,对于当前获取电池电量的方式进行一个整理。
方法一:通过苹果给的api获取
最简单的方式
UIDevice currentDevice].batteryMonitoringEnabled = YES;
double deviceLevel = [UIDevice currentDevice].batteryLevel;
另外一种写法
[UIDevice currentDevice].batteryMonitoringEnabled = YES;
[[NSNotificationCenter defaultCenter]addObserverForName:UIDeviceBatteryLevelDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification*notification) {
NSLog(@"电池电量:%.2f", [UIDevice currentDevice].batteryLevel);
}];
测试多次会出现偏差1%左右,也就是说, 这个办法是存在缺陷的, 最起码, 它不精确。
方法二:通过runtime 获取StatusBar上电池电量控件类私有变量的值,此方法可精准获取iOS6以上电池电量
- (int)getCurrentBatteryLevel
{
UIApplication *app = [UIApplication sharedApplication];
if (app.applicationState == UIApplicationStateActive||app.applicationState==UIApplicationStateInactive) {
Ivar ivar= class_getInstanceVariable([app class],"_statusBar");
id status = object_getIvar(app, ivar);
for (id aview in [status subviews]) {
int batteryLevel = 0;
for (id bview in [aview subviews]) {
if ([NSStringFromClass([bview class]) caseInsensitiveCompare:@"UIStatusBarBatteryItemView"] == NSOrderedSame&&[[[UIDevice currentDevice] systemVersion] floatValue] >=6.0)
{
Ivar ivar= class_getInstanceVariable([bview class],"_capacity");
if(ivar)
{
batteryLevel = ((int (*)(id, Ivar))object_getIvar)(bview, ivar);
//这种方式也可以
/*ptrdiff_t offset = ivar_getOffset(ivar);
unsigned char *stuffBytes = (unsigned char *)(__bridge void *)bview;
batteryLevel = * ((int *)(stuffBytes + offset));*/
NSLog(@"电池电量:%d",batteryLevel);
if (batteryLevel > 0 && batteryLevel <= 100) {
return batteryLevel;
} else {
return 0;
}
}
}
}
}
}
return 0;
}
方法三:找到Mac下IOKit.framework,将IOKit.framework里面的IOPowerSources.h和IOPSKeys.h拷贝到你的iOS项目中。另外, 还需要把IOKit也导入到你的工程中去,此方法也会出现偏差,不精确。
-(double)getCurrentBatteryLevel
{
//Returns a blob of Power Source information in an opaque CFTypeRef.
CFTypeRef blob = IOPSCopyPowerSourcesInfo();
//Returns a CFArray of Power Source handles, each of type CFTypeRef.
CFArrayRef sources = IOPSCopyPowerSourcesList(blob);
CFDictionaryRef pSource = NULL;
const void *psValue;
//Returns the number of values currently in an array.
int numOfSources = CFArrayGetCount(sources);
//Error in CFArrayGetCount
if (numOfSources == 0)
{
NSLog(@"Error in CFArrayGetCount");
return -1.0f;
}
//Calculating the remaining energy
for (int i = 0 ; i < numOfSources ; i++)
{
//Returns a CFDictionary with readable information about the specific power source.
pSource = IOPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(sources, i));
if (!pSource)
{
NSLog(@"Error in IOPSGetPowerSourceDescription");
return -1.0f;
}
psValue = (CFStringRef)CFDictionaryGetValue(pSource, CFSTR(kIOPSNameKey));
int curCapacity = 0;
int maxCapacity = 0;
double percent;
psValue = CFDictionaryGetValue(pSource, CFSTR(kIOPSCurrentCapacityKey));
CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &curCapacity);
psValue = CFDictionaryGetValue(pSource, CFSTR(kIOPSMaxCapacityKey));
CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &maxCapacity);
percent = ((double)curCapacity/(double)maxCapacity * 100.0f);
return percent;
}
return -1.0f;
}