iOS 獲取剩餘電量
阿新 • • 發佈:2019-02-19
最簡單的
[UIDevice currentDevice].batteryMonitoringEnabled = YES;
double deviceLevel = [UIDevice currentDevice].batteryLevel;
方法一:通過蘋果官方文件裡面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
/**
* Calculating the remaining energy
*
* @return Current batterylevel
*/
-(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;
}
方法三:通過runtime 獲取StatusBar上電池電量控制元件類私有變數的值,此方法可精準獲取iOS6以上電池電量
MRC:
- (int)getCurrentBatteryLevel
{
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive||[UIApplication sharedApplication].applicationState==UIApplicationStateInactive) {
void *result = nil;
object_getInstanceVariable([UIApplication sharedApplication], "_statusBar", &result);
id status = result;
for (id aview in [status subviews]) {
for (id bview in [aview subviews]) {
int batteryLevel = 0;
if ([NSStringFromClass([bview class]) caseInsensitiveCompare:@"UIStatusBarBatteryItemView"] == NSOrderedSame&&[[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0)
{
object_getInstanceVariable(bview, "_capacity", &result);
batteryLevel = (int)result;
NSLog(@"電池電量:%d",batteryLevel);
if (batteryLevel > 0 && batteryLevel <= 100) {
return batteryLevel;
} else {
return 0;
}
}
}
}
return 0;
}
ARC:
- (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;
}