iOS代碼層獲取電量

1.加載動態(tài)鏈接庫

iOS是給予Linux內(nèi)核,在Linux調(diào)用如下函數(shù)來加載動態(tài)鏈接庫:dlopen筋讨,dlsym赊舶,dlclose,dlerror

void * dlopen(const char  *filename, int flag);
char * dlerror(void);
void * dlsym(void *handle, const *symbol);
int dlclose(void *handle)

dlopen:以指定模式flag打開指定路徑filename下的動態(tài)鏈接庫文件晒他,并返回一個句柄吱型;其中flag有如下值:

#define RTLD_LAZY   0x1  //對于動態(tài)庫未定義的變量不執(zhí)行解析
#define RTLD_NOW    0x2  //解析每個未定義變量的地址,若解析不出來陨仅,拋NULL異常
#define RTLD_LOCAL  0x4  //使得庫中的解析的定義變量只在當前可以使用
#define RTLD_GLOBAL 0x8 //使得庫中的解析的定義變量在隨后的其它的鏈接庫中變得可以使用

dlerror:返回錯誤信息
dlsym:通過句柄和連接符名稱獲取函數(shù)名或者變量名津滞,一般用于調(diào)用私有的API或者私有變量
dlclose:卸載打開的動態(tài)鏈接庫

2.獲取電量

為了獲取電量mAh的形式,需要使用IOKit.framework灼伤。但是此類庫為私有類庫触徐,所以使用的時候需要動態(tài)引用。偽代碼如下:

a)動態(tài)鏈接IOKit.framework狐赡,獲取并定義函數(shù)指針和變量地址

// 初始化電量管理函數(shù)
- (BOOL) batteryMgInit{
    
// 1.   動態(tài)獲取IOKit句柄撞鹉,選擇RTLD_NOW模式
   _handleIOKit =dlopen(NT_IOKIT_DYLIB_PATH, RTLD_NOW);
    if (!_handleIOKit) {
        return NO;
    }
// 2.   通過IOKit句柄,動態(tài)獲取kIOMasterPortDefault對應的mach port
    _kIOMasterPortDefault = (mach_port_t *)dlsym(_handleIOKit, "kIOMasterPortDefault");
    
// 3.   通過IOKit句柄颖侄,動態(tài)獲取主IOServiceMatching變量
    _mIOServiceMathcing = (NT_IO_SERVICE_MATCHING)dlsym(_handleIOKit, "IOServiceMatching");
    
// 4.   通過IOKit句柄鸟雏,動態(tài)獲取IOServiceGetMatchingService對應的mach port
    _mIOServiceGetMatchingService = (NT_IO_SERVICE_GET_MATCHING_SERVICE)dlsym(_handleIOKit, "IOServiceGetMatchingService");
    
// 5.   通過IOKit句柄,動態(tài)獲取主IORegistryEntryCreateCFProperties函數(shù)地址
    _mIORegistryEntryCreateCFProperties = (NT_IO_REGISTRY_ENTRY_CREATE_CF_PROPERTIES)dlsym(_handleIOKit, "IORegistryEntryCreateCFProperties");
    
// 6.   GT_PFN_IOOBJECTRELEASE為int類型
    _mIOObjectRelease = (NT_IO_OBJECT_RELEASE)dlsym(_handleIOKit, "IOObjectRelease");
    
    
    if (_kIOMasterPortDefault &&
        _mIOServiceMathcing &&
        _mIOServiceGetMatchingService &&
        _mIORegistryEntryCreateCFProperties &&
        _mIOObjectRelease
        ) {
        return YES;
    }
    
    return YES;
}

b)獲取電量參數(shù)

- (void) updateBatteryInfo {
    CFMutableDictionaryRef matching, properties = NULL;
    mach_port_t entry = 0;
//  獲取電量管理對象览祖,_mIOServiceMathcing為動態(tài)獲取IOKit對應函數(shù)(_mIOServiceMathcing)地址指針

//  調(diào)用IOKit的IOServiceMathcing函數(shù)崔慧,獲取IOPMPowerSource對應的matching字典
    matching = _mIOServiceMathcing("IOPMPowerSource");
    if (!matching) {
        return;
    }
    
//
//    func IOServiceGetMatchingService(_ masterPort: mach_port_t,
//                                     _ matching: CFDictionary!) -> io_service_t
//    查詢匹配matching的IOService注冊對象,
    entry = _mIOServiceGetMatchingService(*_kIOMasterPortDefault, matching);
    if (!entry) {
        return;
    }
    

/**
    函數(shù)原型:
    func IORegistryEntryCreateCFProperties(_ entry: io_registry_entry_t,
                                           _ properties: UnsafeMutablePointer<Unmanaged<CFMutableDictionary>?>!,
                                           _ allocator: CFAllocator!,
                                           _ options: IOOptionBits) -> kern_return_t
    IORegistryEntryCreateCFProperties:根據(jù)注冊對象句柄穴墅,將對象屬性存入字典 ***/
    kern_return_t rt = _mIORegistryEntryCreateCFProperties(entry, &properties, NULL, 0);
    if (rt) {
        return;
    }
    
    //  properties提取參數(shù)
    [self updateBatteryItem: (__bridge NSDictionary *)properties];
    CFRelease( properties );
    _mIOObjectRelease( entry );
    
    return;
    
}



- (void) updateBatteryItem:(NSDictionary *)dic{
    
    self.batteryUnit.preCurrentCapacity = self.batteryUnit.currentCapacity;
    
    NSNumber *currentCapacity = [dic objectForKey: @"CurrentCapacity"];
    self.batteryUnit.currentCapacity = [currentCapacity intValue];
    
    NSNumber *maxCapacity = [dic objectForKey: @"MaxCapacity"];
    self.batteryUnit.maxCapacity = [maxCapacity intValue];
    
    NSNumber *voltage = [dic objectForKey:@"Voltage"];
    self.batteryUnit.voltage = [voltage intValue];
}

實驗結果:

demo程序獲取電池當前電量惶室,最大電量,電壓玄货。
如圖分別采樣90s皇钞,和112s兩個時間節(jié)點的電量信息


image.png

90s采樣截圖


5.png

120s采樣截圖

6.png

遇到的問題:由于電池的物理特性,獲取的當前電池電量松捉,最大電池電量的值會發(fā)生變化夹界。如最大電池某個采樣點為1500,下個采樣點為1000隘世;其次上一時刻的當前電量可能會大于這一時刻的電量可柿。
基于上訴原因鸠踪,需要當前電量和最大電池電量配合使用才能較正確的表現(xiàn)當前電池電量情況,即剩余電量百分比(當前電池電量/最大電池電量)

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末复斥,一起剝皮案震驚了整個濱河市营密,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌目锭,老刑警劉巖评汰,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異痢虹,居然都是意外死亡被去,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門奖唯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惨缆,“玉大人,你說我怎么就攤上這事丰捷∽傺耄” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我童漩,道長,這世上最難降的妖魔是什么液斜? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮叠穆,結果婚禮上少漆,老公的妹妹穿的比我還像新娘。我一直安慰自己硼被,他們只是感情好示损,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嚷硫,像睡著了一般检访。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仔掸,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天脆贵,我揣著相機與錄音,去河邊找鬼起暮。 笑死卖氨,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播筒捺,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼柏腻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了系吭?” 一聲冷哼從身側(cè)響起五嫂,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎村斟,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抛猫,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡蟆盹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了闺金。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逾滥。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖败匹,靈堂內(nèi)的尸體忽然破棺而出寨昙,到底是詐尸還是另有隱情,我是刑警寧澤掀亩,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布舔哪,位于F島的核電站,受9級特大地震影響槽棍,放射性物質(zhì)發(fā)生泄漏捉蚤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一炼七、第九天 我趴在偏房一處隱蔽的房頂上張望缆巧。 院中可真熱鬧,春花似錦豌拙、人聲如沸陕悬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捉超。三九已至,卻和暖如春唯绍,著一層夾襖步出監(jiān)牢的瞬間狂秦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工推捐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留裂问,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像堪簿,于是被迫代替她去往敵國和親痊乾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

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