一早敬、私有方法獲取電量相關(guān)的信息
- 可以獲取的信息: 電池的健康程度寞埠、電池容量、是否充電贝室、電源類(lèi)型契讲、傳輸類(lèi)型等
#include <dlfcn.h>
- (NSDictionary*)fetchBatteryInfo
{
mach_port_t *kIOMasterPortDefault;
kern_return_t (*ioRegistryEntryCreateCFProperties)(mach_port_t entry, CFMutableDictionaryRef *properties, CFAllocatorRef allocator, UInt32 options) = NULL;
mach_port_t (*ioServiceGetMatchingService)(mach_port_t masterPort, CFDictionaryRef matching CF_RELEASES_ARGUMENT) = NULL;
CFMutableDictionaryRef (*ioServiceMatching)(const char *name) = NULL;
CFTypeRef (*ioPSCopyPowerSourcesInfo)(void) = NULL;
CFArrayRef (*ioPSCopyPowerSourcesList)(CFTypeRef blob) = NULL;
CFDictionaryRef (*ioPSGetPowerSourceDescription)(CFTypeRef blob, CFTypeRef ps) = NULL;
CFMutableDictionaryRef powerSourceService = NULL;
mach_port_t platformExpertDevice = 0;
var handle = dlopen("/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit", RTLD_LAZY);
ioRegistryEntryCreateCFProperties = dlsym(handle, "IORegistryEntryCreateCFProperties");
kIOMasterPortDefault = dlsym(handle, "kIOMasterPortDefault");
ioServiceMatching = dlsym(handle, "IOServiceMatching");
ioServiceGetMatchingService = dlsym(handle, "IOServiceGetMatchingService");
ioPSCopyPowerSourcesInfo = dlsym(handle, "IOPSCopyPowerSourcesInfo");
ioPSCopyPowerSourcesList = dlsym(handle, "IOPSCopyPowerSourcesList");
ioPSGetPowerSourceDescription = dlsym(handle, "IOPSGetPowerSourceDescription");
if (ioRegistryEntryCreateCFProperties != NULL &&
ioServiceMatching != NULL &&
ioServiceGetMatchingService != NULL)
{
powerSourceService = ioServiceMatching("IOPMPowerSource");
platformExpertDevice = ioServiceGetMatchingService(*kIOMasterPortDefault, powerSourceService);
}
NSMutableDictionary *batteryInfo = nil;
if(powerSourceService != NULL && platformExpertDevice != 0)
{
CFMutableDictionaryRef prop = NULL;
ioRegistryEntryCreateCFProperties(platformExpertDevice, &prop, 0, 0);
if(prop != NULL)
{
batteryInfo = [NSMutableDictionary dictionaryWithDictionary:(NSDictionary*)prop];
CFRelease(prop);
}
}
var blob = ioPSCopyPowerSourcesInfo();
var sources = ioPSCopyPowerSourcesList(blob);
CFDictionaryRef pSource = NULL;
var numOfSources = CFArrayGetCount(sources);
for(CFIndex i = 0; i < numOfSources; I++)
{
pSource = ioPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(sources, i));
if(pSource != NULL)
{
if(batteryInfo == nil)
batteryInfo = [NSMutableDictionary dictionaryWithDictionary:(NSDictionary*)pSource];
else
[batteryInfo setValuesForKeysWithDictionary:(NSDictionary*)pSource];
break;
}
}
dlclose(handle);
CFRelease(blob);
CFRelease(sources);
return batteryInfo;
}
- 越高版本的數(shù)據(jù)越少,蘋(píng)果審核很難通過(guò)
- iOS 12.2 iPhone X 結(jié)果如下
{
"Battery Provides Time Remaining" = 1;
BatteryHealth = Poor;
BatteryHealthCondition = "Check Battery";
BatteryInstalled = 1;
"Current Capacity" = 100;
ExternalConnected = 1;
"Is Charged" = 1;
"Is Charging" = 0;
"Is Present" = 1;
"Max Capacity" = 100;
Name = "InternalBattery-0";
"Power Source ID" = 2424931;
"Power Source State" = "AC Power";
"Raw External Connected" = 1;
"Show Charging UI" = 1;
"Time to Empty" = 0;
"Time to Full Charge" = 0;
"Transport Type" = Internal;
Type = InternalBattery;
}
- ios 10.3 iPhone 5c
{
AdapterInfo = 16384;
AtCriticalLevel = 0;
"Battery Provides Time Remaining" = 1;
BatteryHealth = Good;
Current = 1000;
"Current Capacity" = 87;
CurrentCapacity = 1131;
DesignCycleCount = 300;
ExternalChargeCapable = 1;
ExternalConnected = 1;
FullyCharged = 0;
IOClass = AppleARMPMUCharger;
"Is Charging" = 1;
"Is Finishing Charge" = 0;
"Is Present" = 1;
IsCharging = 1;
"Max Capacity" = 100;
MaxCapacity = 1300;
Name = "InternalBattery-0";
"Power Source ID" = 4063331;
"Power Source State" = "AC Power";
"Raw External Connected" = 1;
"Show Charging UI" = 1;
"Time to Empty" = 0;
"Time to Full Charge" = 0;
"Transport Type" = Internal;
Type = InternalBattery;
Voltage = 4178;
}
二滑频、sysdiagnose
- 證書(shū)下載地址
- 安裝方式
- Apple Configurator 2
- AirDrop
- 安裝完成后在不重啟手機(jī)的情況下捡偏,等待10到30分鐘。
- 通過(guò) iTunes同步到電腦上峡迷。
- 去 ~/Library/Logs/CrashReporter/MobileDevice 目錄下银伟,打開(kāi) powerlog_xxxx.PLSQL 文件
-
可以獲取到最近幾天的所有電量信息
image.png
三、系統(tǒng)提供接口
- 可以獲取到整體的電池利用率绘搞,以及充電狀態(tài)
// #import <UIKit / UIDevice.h>
UIDevice * device = [UIDevice currentDevice ];
device.batteryMonitoringEnabled = YES ;
//彤避。的UIDevice返回的batteryLevel的范圍在0到1之間
NSUInteger batteryLevel = device.batteryLevel * 100 ;
//獲取充電狀態(tài)
UIDeviceBatteryState state = device.batteryState;
if(state == UIDeviceBatteryStateCharging || state == UIDeviceBatteryStateFull){
//正在充電和電池已滿(mǎn)
}
四、Ecergy Log
-
iOS設(shè)置選項(xiàng) - >開(kāi)發(fā)者選項(xiàng) - >日志記錄 - >開(kāi)始錄制
image.png 進(jìn)行需要測(cè)試電量的場(chǎng)景操作后進(jìn)入開(kāi)發(fā)者選項(xiàng)點(diǎn)擊停止錄制
iOS設(shè)備和Mac連接
打開(kāi)儀器夯辖,選擇能量診斷
-
選擇文件>從設(shè)備導(dǎo)入記錄的數(shù)據(jù)
image.png 結(jié)合 Time Profiler 工具琉预,可以大概定位能耗比較高的代碼,參考地址
五蒿褂、Energy Impact
可以大致確定程序運(yùn)行中的能耗情況圆米, 結(jié)合 Time Profiler 工具進(jìn)行代碼定位
-
真機(jī)運(yùn)行項(xiàng)目,選擇Energy Impact
image.png 藍(lán)色表示--合理,黃色--表示程序比較耗電,紅色--表示僅僅輕度使用你的程序,就會(huì)很耗電.
圖表中Utilization欄中是表示瞬時(shí)耗電情況
圖表中Average欄中,表示平均耗電情況
圖表中Energy Impact中cost(藍(lán)色)表示運(yùn)行項(xiàng)目代碼需要電量,Overhead(紅色)表示開(kāi)銷(xiāo),包括CPU的喚起,無(wú)線電模組(藍(lán)牙&WiFi),和其他系統(tǒng)資源的調(diào)用等
灰色表示有電量消耗,白色表示沒(méi)有電量消耗
-
影響電量的五個(gè)因素,
- CPU : 使用率超過(guò)20%就會(huì)快速耗干電池電量.高效使用CPU,并且當(dāng)用戶(hù)出現(xiàn)模糊輸入時(shí)快速做出不做事情的反應(yīng).
- Network : 網(wǎng)絡(luò)活動(dòng)會(huì)喚起需要長(zhǎng)時(shí)間周期性供電的無(wú)線電模組,可以分批次進(jìn)行網(wǎng)絡(luò)請(qǐng)求,來(lái)降低開(kāi)銷(xiāo).
- Location : 精密&高頻的的定位會(huì)增加開(kāi)銷(xiāo),需要按需使用.
- GPU : 圖形處理器(顯卡的處理器),亂使用GPU會(huì)導(dǎo)致交互差,并且降低電池壽命.
- Background : 后臺(tái)狀態(tài)App仍會(huì)消耗電量,App要按需執(zhí)行后臺(tái)操作,并使用延遲APIs來(lái)保證系統(tǒng)運(yùn)算高效執(zhí)行.另外,在app進(jìn)入后臺(tái)狀態(tài)是,立即減少動(dòng)作,并且通知系統(tǒng)一次這些動(dòng)作已經(jīng)完成.