關(guān)于iOS電量檢測(cè)和分析的調(diào)研

一早敬、私有方法獲取電量相關(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ū)下載地址
  • 安裝方式
  • 安裝完成后在不重啟手機(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)完成.
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末啄栓,一起剝皮案震驚了整個(gè)濱河市娄帖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌昙楚,老刑警劉巖近速,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異堪旧,居然都是意外死亡削葱,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)淳梦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)佩耳,“玉大人,你說(shuō)我怎么就攤上這事谭跨「珊瘢” “怎么了李滴?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蛮瞄。 經(jīng)常有香客問(wèn)我所坯,道長(zhǎng),這世上最難降的妖魔是什么挂捅? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任芹助,我火速辦了婚禮,結(jié)果婚禮上闲先,老公的妹妹穿的比我還像新娘状土。我一直安慰自己,他們只是感情好伺糠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布蒙谓。 她就那樣靜靜地躺著,像睡著了一般训桶。 火紅的嫁衣襯著肌膚如雪累驮。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天舵揭,我揣著相機(jī)與錄音谤专,去河邊找鬼。 笑死午绳,一個(gè)胖子當(dāng)著我的面吹牛置侍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拦焚,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蜡坊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了耕漱?” 一聲冷哼從身側(cè)響起算色,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤抬伺,失蹤者是張志新(化名)和其女友劉穎螟够,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體峡钓,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妓笙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了能岩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寞宫。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拉鹃,靈堂內(nèi)的尸體忽然破棺而出辈赋,到底是詐尸還是另有隱情鲫忍,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布钥屈,位于F島的核電站悟民,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏篷就。R本人自食惡果不足惜射亏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望竭业。 院中可真熱鬧智润,春花似錦、人聲如沸未辆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鼎姐。三九已至钾麸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炕桨,已是汗流浹背饭尝。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留献宫,地道東北人钥平。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像姊途,于是被迫代替她去往敵國(guó)和親涉瘾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 本次分享會(huì)目的 通過(guò)對(duì)增加對(duì) Android Profile Tools 的了解捷兰,提高大家工作過(guò)程中定位和解決Bu...
    嘟嘟賭起閱讀 7,246評(píng)論 0 4
  • 一立叛、耗電量檢測(cè) 1、進(jìn)入手機(jī)"設(shè)置"->"電池",可以直觀的看出來(lái)手機(jī)應(yīng)用的耗電情況贡茅。 2秘蛇、使用Xcode打開(kāi)你的...
    彭磊PL閱讀 2,182評(píng)論 0 2
  • 耗電量檢測(cè) 1.進(jìn)入手機(jī)"設(shè)置" -> "電池",可以直觀的看出來(lái)手機(jī)應(yīng)用的耗電情況. 2.使用xcode打開(kāi)你的...
    陳俊峰閱讀 34,429評(píng)論 13 116
  • 我要走了 你自保重 縱有千言萬(wàn)語(yǔ) 化作漫天繁星 雨絲深凝……
    弘毅123閱讀 328評(píng)論 0 0
  • 題記:堅(jiān)持一件事赁还,難度系數(shù)是比較高的,上一篇文章《趙雷歌聲中的“成都”驹沿,其實(shí)每個(gè)人心中都有》還沒(méi)有寫(xiě)完艘策,晚上時(shí)間已...
    微鳴艾特羊閱讀 338評(píng)論 0 0