美文网首页iOS基础篇
关于iOS电量检测和分析的调研

关于iOS电量检测和分析的调研

作者: child_cool | 来源:发表于2019-06-20 10:39 被阅读0次

一、私有方法获取电量相关的信息

  • 可以获取的信息: 电池的健康程度、电池容量、是否充电、电源类型、传输类型等
#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;
}
  • 越高版本的数据越少,苹果审核很难通过
  • iOS 12.2 iPhone X 结果如下
{
    "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

  • 证书下载地址
  • 安装方式
  • 安装完成后在不重启手机的情况下,等待10到30分钟。
  • 通过 iTunes同步到电脑上。
  • 去 ~/Library/Logs/CrashReporter/MobileDevice 目录下,打开 powerlog_xxxx.PLSQL 文件
  • 可以获取到最近几天的所有电量信息


    image.png

三、系统提供接口

  • 可以获取到整体的电池利用率,以及充电状态
 // #import <UIKit / UIDevice.h> 
   UIDevice * device = [UIDevice currentDevice ];
   device.batteryMonitoringEnabled = YES ;
   //。的UIDevice返回的batteryLevel的范围在0到1之间
   NSUInteger batteryLevel = device.batteryLevel * 100 ;
   //获取充电状态
   UIDeviceBatteryState state = device.batteryState;
   if(state == UIDeviceBatteryStateCharging || state == UIDeviceBatteryStateFull){
        //正在充电和电池已满 
   }

四、Ecergy Log

  • iOS设置选项 - >开发者选项 - >日志记录 - >开始录制


    image.png
  • 进行需要测试电量的场景操作后进入开发者选项点击停止录制

  • iOS设备和Mac连接

  • 打开仪器,选择能量诊断

  • 选择文件>从设备导入记录的数据


    image.png
  • 结合 Time Profiler 工具,可以大概定位能耗比较高的代码,参考地址

五、Energy Impact

  • 可以大致确定程序运行中的能耗情况, 结合 Time Profiler 工具进行代码定位

  • 真机运行项目,选择Energy Impact


    image.png
  • 蓝色表示--合理,黄色--表示程序比较耗电,红色--表示仅仅轻度使用你的程序,就会很耗电.

  • 图表中Utilization栏中是表示瞬时耗电情况

  • 图表中Average栏中,表示平均耗电情况

  • 图表中Energy Impact中cost(蓝色)表示运行项目代码需要电量,Overhead(红色)表示开销,包括CPU的唤起,无线电模组(蓝牙&WiFi),和其他系统资源的调用等

  • 灰色表示有电量消耗,白色表示没有电量消耗

  • 影响电量的五个因素,

    • CPU : 使用率超过20%就会快速耗干电池电量.高效使用CPU,并且当用户出现模糊输入时快速做出不做事情的反应.
    • Network : 网络活动会唤起需要长时间周期性供电的无线电模组,可以分批次进行网络请求,来降低开销.
    • Location : 精密&高频的的定位会增加开销,需要按需使用.
    • GPU : 图形处理器(显卡的处理器),乱使用GPU会导致交互差,并且降低电池寿命.
    • Background : 后台状态App仍会消耗电量,App要按需执行后台操作,并使用延迟APIs来保证系统运算高效执行.另外,在app进入后台状态是,立即减少动作,并且通知系统一次这些动作已经完成.

相关文章

网友评论

    本文标题:关于iOS电量检测和分析的调研

    本文链接:https://www.haomeiwen.com/subject/kgxlqctx.html