Battery

作者: 81bad73e9053 | 来源:发表于2017-07-04 15:01 被阅读69次

    执行代码(显而易见)
    数据传输(上传和下载,使用WiFi,2G,3G,4G)
    定位
    传感器
    渲染图像
    唤醒任务

    adb kill-server

    adb devices

    adb shell dumpsys batterystats --reset

    上面的操作执行完毕后,拔掉手机,操作你的App,操作完成后,重新连接手机,执行下面的命令,收集Battery数据:
    adb shell dumpsys batterystats > batterystats.txt
    得到这些数据后,这个时候使用我们的battery-historian来生成我们可见HTML报告:
    Python historian.py batterystats.txt > batterystats.html

    Battery Historian

    最强大、最推荐的工具:Battery Historian是Android5.0之后Google开源的一款用于检测与电池有关的信息和事件的工具,从设备中收集电池数据,然后使用Battery Historian可以可视化分析相关指标如耗电比例、Wifi、蜂窝数据量、WakeLock唤醒次数。随着Android6.0更新了Battery Historian 2.0加入引起手机状态变化的应用。

    通过Battery Historian可以方便的看到各耗电模块随着时间的耗电情况:包含操作类型、执行时间、对应App等;还可以进行筛选特定的App,给出一个总结性的说明,包括:Network Information、 Syncs、WakeLock、Services、Process info、Scheduled Job、Sensor Use等,查看每一个模块的总结,可以看出来每一项的耗时以及执行次数。当发现异常的时候可以针对性的进行排查。总之:Battery Historian真的很强大

    http://duanqz.github.io/2015-07-21-batterystats-part1

    1.CPU时间片优化

    1.充电进行某些操作
    某些不需要及时与用户进行交互的操作,可以放到充电后再进行,比如拍照后图片处理,360手机助手在手机充电后才自动清理
    垃圾,联系人数据上传到云端等等。。。

    
    监听电池充电操作
    IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    Intent batteryStatus = this.registerReceiver(null, filter);
    
    //几种充电方式:直流充电,USB充电,无线充电
        int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
            boolean usbCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_USB);
            boolean acCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_AC);
            boolean wirelessCharge = false;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                wirelessCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_WIRELESS);
            }
            return (usbCharge || acCharge || wirelessCharge);
        }
    

    2.WIFI状态下进行操作

    我们知道在蜂窝无线网络状态下会比WIFI状态下耗电的多,所以尽量减少移动网络下的数据传输,多在WIFI数据下操作!
    //判断网络连接 
    

    3.网络请求设置超时
    在网络请求时,如果网络很差,请求需要很长时间,我们需要设置超时时间,减少网络消耗!

    4.任务集中处理JobScheduler
    使用JobScheduler来处理一些特定的操作

    
    JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
            for (int i = 0; i < 10; i++) {
                JobInfo jobInfo = new JobInfo.Builder(i,componentname)
                        .setMinimumLatency(10000)//最小延时
                        .setOverrideDeadline(60000)//最多执行时间
    //                    .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)//免费的网络(wifi/蓝牙/USB),满足该条件才去执行
    .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)//任意网络---wifi
                        .build();
                jobScheduler.schedule(jobInfo);
            }
    // 任务处理
    public class JobServiceTest extends JobService {}
    缺点就是有API限制
    

    5.WEAK_LOCK谨慎使用
    WEAK_LOCK主要是用来处理系统休眠的,我们知道系统为了省电一般会在熄屏之后进行休眠,休眠之后所有的操作就会被暂停冷冻了(Timer,Services),
    休眠之后一些后台的网络访问操作就会被停止,可能就会导致一些问题,比如即时通讯的心跳包不能及时发出,导致收不到消息,
    为了防止这些情况,需要使用WEAK_LOCK来唤醒CPU,权利配合我们的程序执行!

    wake_lock:两种锁,一种计数锁(锁一次,释放一次);非计数锁(锁了很多次,只需要release一次就可以解除了

    
    
    // 注册权限
        <uses-permission android:name="android.permission.INTERNET"></uses-permission>
        <uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
    
        PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
        WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MyWakelockTag");
    
      mWakelock.acquire();//唤醒CPU
      mWakelock.release();//释放CPU锁
    注意:在使用该类的时候,必须保证acquire和release是成对出现的。
    

    3.3 GPS

    定位是App中常用的功能,但是定位不能千篇一律,不同的场景以及不同类型的App对定位更加需要个性化的区分。

    3.3.1 选择合适的Location Provider

    Android系统支持多个Location Provider:

    GPS_PROVIDER:
    GPS定位,利用GPS芯片通过卫星获得自己的位置信息。定位精准度高,一般在10米左右,耗电量大;但是在室内,GPS定位基本没用。

    NETWORK_PROVIDER:
    网络定位,利用手机基站和WIFI节点的地址来大致定位位置,这种定位方式取决于服务器,即取决于将基站或WIF节点信息翻译成位置信息的服务器的能力。

    PASSIVE_PROVIDER:
    被动定位,就是用现成的,当其他应用使用定位更新了定位信息,系统会保存下来,该应用接收到消息后直接读取就可以了。比如如果系统中已经安装了百度地图,高德地图(室内可以实现精确定位),你只要使用它们定位过后,再使用这种方法在你的程序肯定是可以拿到比较精确的定位信息。

    使用Criteria,设置合适的模式、功耗、海拔、速度等需求,系统会返回合适的Location Provider。

    例如你的App只是需要一个粗略的定位那么就不需要使用GPS进行定位,既耗费电量,定位的耗时也久。

    3.3.2 及时注销定位监听

    在获取到定位之后或者程序处于后台时,注销定位监听,此时监听GPS传感器相当于执行no-op(无操作指令),用户不会有感知但是却耗电。

    public void onPause() {
        super.onPause();
        locationManager.removeListener(locationListener);
    }
    
    public void onResume(){
        super.onResume();
        locationManager.requestLocationUpdates(locationManager.getBestProvider(criteria, true),6000,100,locationListener);
    }
    

    3.3.3 多模块使用定位尽量复用

    多个模块使用定位,尽量复用上一次的结果,而不是都重新走定位的过程,节省电量损耗;例如:在应用启动的时候获取一次定位,保存结果,之后再用到定位的地方都直接去取。

    谨慎使用WakeLock

    Android为了节省电量,会在用户无操作一段时间之后进入休眠状态。Wake Lock是一种锁的机制,只要有人拿着这个锁,系统就无法进入休眠。一些App为了能在后台持续做事情,就会持有一个WakeLock,那么手机就不会进入休眠状态,App要做的事情能做了,但是也更加耗电。

    App在前台不要申请WakeLock,此时无需申请,申请的话会计算到应用电量消耗;
    App在后台由于业务需要必须要申请WakeLock时使用带有超时参数的方法,防止由于忘记或者异常情况下没有释放;
    App申请使用WakeLock,任务结束之后及时释放,让系统再次进入休眠状态。
    PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
    PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK| PowerManager.ON_AFTER_RELEASE,TAG);
    wl.acquire(TIMEOUT);// 使用带有超时参数的acquire方法
    // ... do work...
    wl.release();

    传感器使用

    使用传感器,选择合适的采样率,越高的采样率类型则越费电;

    SENSOR_DELAY_NOMAL (200000微秒)

    SENSOR_DELAY_UI (60000微秒)

    SENSOR_DELAY_GAME (20000微秒)

    SENSOR_DELAY_FASTEST (0微秒)

    在后台时注意及时注销传感器监听

    https://juejin.im/post/58fef4771b69e60058aab2d1
    https://juejin.im/post/579f251e8ac247005fed1be7
    http://www.jianshu.com/p/afd4d8a6dcd6
    http://javayhu.me/blog/2017/01/24/how-to-know-your-applications-battery-stats/
    http://blog.csdn.net/itfootball/article/details/49004699
    http://blog.csdn.net/itfootball/article/details/44084159
    http://www.07net01.com/linux/2016/01/1207924.html
    http://www.jianshu.com/p/f4b710b13e6d
    https://blog.wilddog.com/?p=948
    http://hukai.me/android-performance-battery/
    http://blog.csdn.net/zhaodecang/article/details/53345861
    http://www.jianshu.com/p/5d83d8649c98
    https://www.zhihu.com/question/37483907
    https://blog.wilddog.com/?cat=67
    http://duanqz.github.io/2015-07-21-batterystats-part1

    1.使用AlarmManager
    AlarmManager是系统的闹钟服务,可以用来唤醒CPU,做一些后台的任务,即使在屏幕熄灭后也能正常的工作(定时任务尽量不要使用Timer、Handler、Thread、Service)

    Intent intent = new Intent(context, Service.class);
    PendingIntent pi = PendingIntent.getService(context, 1, intent, 0);
    AlarmManager alarm = (AlarmManager) getSystemService(Service.ALARM_SERVICE);
    if(alarm != null)
    {
    alarm.cancel(pi);
    // 闹钟在系统睡眠状态下会唤醒系统并执行提示功能
    alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 1000, 2000, pi);// 确切的时间闹钟//alarm.setExact(…);
    //alarm.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pi);
    }

    相关文章

      网友评论

          本文标题:Battery

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