iOS开发之runtime精准获取电池电量
方法一:通过苹果官方文档里面UIDevice public API来获取,代码如下: [UIDevice currentDevice].batteryMonitoringEnabled = YES; [[NSNotificationCenter defaultCenter] addObserverForName:UIDeviceBatteryLevelDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification) { // Level has changed NSLog(@"Battery Level Change"); NSLog(@"电池电量:%.2f", [UIDevice currentDevice].batteryLevel); }];@property(nonatomic,readonly) float batteryLevel NS_AVAILABLE_IOS(3_0); // 0 .. 1.0. -1.0 if UIDeviceBatteryStateUnknown它返回的是0.00-1.00之间的浮点值。 但是经过测试发现,在iOS7 上 它是以0.05为单位的,但是在iOS9下测试,它是以0.01为单位的,虽然也是0.01为单位,但是测试多次也会出现偏差1%左右。也就是说, 这个办法是存在缺陷的, 最起码, 它不精确。 方法二:找到Mac下IOKit.framework,将IOKit.framework里面的IOPowerSources.h和IOPSKeys.h拷贝到你的iOS项目中。另外, 还需要把IOKit也导入到你的工程中去,此方法也会出现偏差,不精确。DEMO 地址:https://github.com/colin1994/batteryLevelTest.git /** *Calculatingtheremainingenergy * *@returnCurrentbatterylevel */-(double)getCurrentBatteryLevel { //ReturnsablobofPowerSourceinformationinanopaqueCFTypeRef.CFTypeRefblob=IOPSCopyPowerSourcesInfo(); //ReturnsaCFArrayofPowerSourcehandles,eachoftypeCFTypeRef.CFArrayRefsources=IOPSCopyPowerSourcesList(blob); CFDictionaryRefpSource=NULL; constvoid*psValue; //Returnsthenumberofvaluescurrentlyinanarray.intnumOfSources=CFArrayGetCount(sources); //ErrorinCFArrayGetCountif(numOfSources==0) { NSLog(@"ErrorinCFArrayGetCount"); return-1.0f; } //Calculatingtheremainingenergyfor(inti=0;i<numOfSources;i++) { //ReturnsaCFDictionarywithreadableinformationaboutthespecificpowersource. pSource=IOPSGetPowerSourceDescription(blob,CFArrayGetValueAtIndex(sources,i)); if(!pSource) { NSLog(@"ErrorinIOPSGetPowerSourceDescription"); return-1.0f; } psValue=(CFStringRef)CFDictionaryGetValue(pSource,CFSTR(kIOPSNameKey)); intcurCapacity=0; intmaxCapacity=0; doublepercent; 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); returnpercent; } return-1.0f; } 方法三:通过runtime 获取StatusBar上电池电量控件类私有变量的值,此方法可精准获取iOS6以上电池电量 MRC: -(int)getCurrentBatteryLevel {if([UIApplicationsharedApplication].applicationState==UIApplicationStateActive||[UIApplicationsharedApplication].applicationState==UIApplicationStateInactive){void*result=nil; object_getInstanceVariable([UIApplicationsharedApplication],"_statusBar",&result);idstatus=result;for(idaviewin[statussubviews]){for(idbviewin[aviewsubviews]){intbatteryLevel=0;if([NSStringFromClass([bviewclass])caseInsensitiveCompare:@"UIStatusBarBatteryItemView"]==NSOrderedSame&&[[[UIDevicecurrentDevice]systemVersion]floatValue]>=6.0) { object_getInstanceVariable(bview,"_capacity",&result); batteryLevel=(int)result;NSLog(@"电池电量:%d",batteryLevel);if(batteryLevel>0&&batteryLevel<=100){returnbatteryLevel; }else{return0; } } } }return0; } ARC: -(int)getCurrentBatteryLevel {UIApplication*app=[UIApplicationsharedApplication];if(app.applicationState==UIApplicationStateActive||app.applicationState==UIApplicationStateInactive){ Ivarivar=class_getInstanceVariable([appclass],"_statusBar");idstatus=object_getIvar(app,ivar);for(idaviewin[statussubviews]){intbatteryLevel=0;for(idbviewin[aviewsubviews]){if([NSStringFromClass([bviewclass])caseInsensitiveCompare:@"UIStatusBarBatteryItemView"]==NSOrderedSame&&[[[UIDevicecurrentDevice]systemVersion]floatValue]>=6.0) { Ivarivar=class_getInstanceVariable([bviewclass],"_capacity");if(ivar) { batteryLevel=((int(*)(id,Ivar))object_getIvar)(bview,ivar);//这种方式也可以 /*ptrdiff_toffset=ivar_getOffset(ivar); unsignedchar*stuffBytes=(unsignedchar*)(__bridgevoid*)bview; batteryLevel=*((int*)(stuffBytes+offset));*/ NSLog(@"电池电量:%d",batteryLevel);if(batteryLevel>0&&batteryLevel<=100){returnbatteryLevel; }else{return0; } } } } } }return0; } 本文转自 卓行天下 51CTO博客,原文链接:http://blog.51cto.com/9951038/1831743,如需转载请自行联系原作者