linux系统实时获取电量,iOS代码层获取电量

1.加载动态链接库

iOS是给予Linux内核,在Linux调用如下函数来加载动态链接库: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下的动态链接库文件,并返回一个句柄;其中flag有如下值:

#define RTLD_LAZY 0x1 //对于动态库未定义的变量不执行解析

#define RTLD_NOW 0x2 //解析每个未定义变量的地址,若解析不出来,抛NULL异常

#define RTLD_LOCAL 0x4 //使得库中的解析的定义变量只在当前可以使用

#define RTLD_GLOBAL 0x8 //使得库中的解析的定义变量在随后的其它的链接库中变得可以使用

dlerror:返回错误信息

dlsym:通过句柄和连接符名称获取函数名或者变量名,一般用于调用私有的API或者私有变量

dlclose:卸载打开的动态链接库

2.获取电量

为了获取电量mAh的形式,需要使用IOKit.framework。但是此类库为私有类库,所以使用的时候需要动态引用。伪代码如下:

a)动态链接IOKit.framework,获取并定义函数指针和变量地址

// 初始化电量管理函数

- (BOOL) batteryMgInit{

// 1. 动态获取IOKit句柄,选择RTLD_NOW模式

_handleIOKit =dlopen(NT_IOKIT_DYLIB_PATH, RTLD_NOW);

if (!_handleIOKit) {

return NO;

}

// 2. 通过IOKit句柄,动态获取kIOMasterPortDefault对应的mach port

_kIOMasterPortDefault = (mach_port_t *)dlsym(_handleIOKit, "kIOMasterPortDefault");

// 3. 通过IOKit句柄,动态获取主IOServiceMatching变量

_mIOServiceMathcing = (NT_IO_SERVICE_MATCHING)dlsym(_handleIOKit, "IOServiceMatching");

// 4. 通过IOKit句柄,动态获取IOServiceGetMatchingService对应的mach port

_mIOServiceGetMatchingService = (NT_IO_SERVICE_GET_MATCHING_SERVICE)dlsym(_handleIOKit, "IOServiceGetMatchingService");

// 5. 通过IOKit句柄,动态获取主IORegistryEntryCreateCFProperties函数地址

_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)获取电量参数

- (void) updateBatteryInfo {

CFMutableDictionaryRef matching, properties = NULL;

mach_port_t entry = 0;

// 获取电量管理对象,_mIOServiceMathcing为动态获取IOKit对应函数(_mIOServiceMathcing)地址指针

// 调用IOKit的IOServiceMathcing函数,获取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;

}

/**

函数原型:

func IORegistryEntryCreateCFProperties(_ entry: io_registry_entry_t,

_ properties: UnsafeMutablePointer?>!,

_ allocator: CFAllocator!,

_ options: IOOptionBits) -> kern_return_t

IORegistryEntryCreateCFProperties:根据注册对象句柄,将对象属性存入字典 ***/

kern_return_t rt = _mIORegistryEntryCreateCFProperties(entry, &properties, NULL, 0);

if (rt) {

return;

}

// properties提取参数

[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两个时间节点的电量信息

14e183d385f5

image.png

90s采样截图

14e183d385f5

5.png

120s采样截图

14e183d385f5

6.png

遇到的问题:由于电池的物理特性,获取的当前电池电量,最大电池电量的值会发生变化。如最大电池某个采样点为1500,下个采样点为1000;其次上一时刻的当前电量可能会大于这一时刻的电量。

基于上诉原因,需要当前电量和最大电池电量配合使用才能较正确的表现当前电池电量情况,即剩余电量百分比(当前电池电量/最大电池电量)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值