Android性能优化——电量

Android 进阶——性能优化之电量优化全攻略及实战小结(一) 性能优化之电量优化之低电耗模式和应用待机模式概述 阅读详情

Android性能优化——电量

原Udacity视频链接

1. 理解电池消耗

手机各个硬件模块的耗电量是不一样的,有些模块非常耗电,而有些模块则相对显得耗电量小很多。

android_perf_battery_drain

电量消耗的计算与统计是一件麻烦而且矛盾的事情,记录电量消耗本身也是一个费电量的事情。唯一可行的方案是使用第三方监测电量的设备,这样才能够获取到真实的电量消耗。

当设备处于待机状态时消耗的电量是极少的,以N5为例,打开飞行模式,可以待机接近1个月。可是点亮屏幕,硬件各个模块就需要开始工作,这会需要消耗很多电量。

使用WakeLock或者JobScheduler唤醒设备处理定时的任务之后,一定要及时让设备回到初始状态。每次唤醒蜂窝信号进行数据传递,都会消耗很多电量,它比WiFi等操作更加的耗电。

在这里插入图片描述

2. Battery Historian

Battery Historian是Android 5.0开始引入的新API。通过下面的指令,可以得到设备上的电量消耗信息:

adb shell dumpsys batterystats > xxx.txt  //得到整个设备的电量消耗信息
adb shell dumpsys batterystats > com.package.name > xxx.txt //得到指定app相关的电量消耗信息

得到了原始的电量消耗数据之后,我们需要通过Google编写的一个Python脚本把数据信息转换成可读性更好的html文件,打开这个转换过后的html文件,可以看到生成的列表数据。
在这里插入图片描述

3. 充电状态和BatteryManager

我们可以通过如下代码获取现在的充电状态是否为AC充电。

IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = this.registerReceiver(null, filter);
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean acCharge = (chargePlug == BatteryManager.BATTERY_PLUGGED_AC);
if (acCharge) {
    Log.v(LOG_TAG,“The phone is charging!”);
}

得到充电的状态之后我们可以有针对性的做一些操作,比如在充电时执行一些耗时的代码。

private boolean checkForPower() {
    // It is very easy to subscribe to changes to the battery state, but you can get the current
    // state by simply passing null in as your receiver.  Nifty, isn't that?
    IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    Intent batteryStatus = this.registerReceiver(null, filter);

    // There are currently three ways a device can be plugged in. We should check them all.
    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);
}

上面代码可以得到现在是否充电。

4. Wakelock和电池消耗

Android会不断关闭各种硬件来延长大量的硬件来延长手机的待机时间,首先屏幕会变暗直至关闭,然后CPU进入睡眠。但是即使在这种睡眠的状态下,大多数应用还是会尝试进行工作,他们将不断的唤醒手机。

最简单的唤醒手机的方法是使用WakeLock的API来保持CPU工作。这样手机可以简单的被唤醒工作,但是及时释放WakeLock是非常重要的,不恰当的使用WakeLock会导致很严重的后果。例如如果应用在上传图片内容时不是用预期的10秒,而是花了60分钟来分析。或者服务器崩溃了怎么办,社交媒体的服务器再也没有回应,要一直等下去了。这会导致你的手机保持开启状态 ,一直等待这些内容,这样很快手机电量就耗完了。

这就是我们需要使用带时间参数的wakelock.acquire()的原因。

在上述意外情况出现时会强制释放唤醒锁。

但是这也不能完全解决问题。这些情况下我们该如何设置时间参数值呢,使用唤醒锁并重试前,等待多久才比较合适呢?

正确的解决方法可能是,使用不精准的计时器。通常情况下,我们会设定一个时间进行某个操作,但是动态修改这个时间也许会更好。例如,如果有另外一个程序需要比你设定的时间晚5分钟唤醒,最好能够等到那个时候,两个任务捆绑一起同时进行,这就是非精确定时器的核心工作原理。我们可以定制计划的任务,可是系统如果检测到一个更好的时间,它可以推迟你的任务,以节省电量消耗。

在这里插入图片描述
现实中,有很多情况,可以进行集中电池工作更好。比如手机充电时,或连接了WIFI,或已经被另一进程唤醒。如果你的工作可以延迟到将来某一时刻,延迟到到更理想的时刻 ,那么你会大大提高低电池寿命。这就是任务调度API的功能。这个API在规划未来工作,提升电池性能上发挥了很大作用。例如,非用户操作可等到手机连接电源,或接入WIFI时在进行,或者在某一时间内集中处理任务。

5. 网络和电池消耗

对电池来说,网络连接是最耗电的工作。手机里面有一个芯片,Ham radio,他的功能就是连接当地的电话信号塔并和它们进行大量的数据传输。但是这个芯片不是一直活跃的,一旦你发送了数据,无线芯片会在一定时间内保持开启状态再接收返回的数据。但是如果没有活动,这个硬件就会休眠以节省电量。

通过前面学习到的Battery Historian我们可以得到设备的电量消耗数据。
在这里插入图片描述
每一个红色的栏都代表一个活跃的移动无线网,空隙代表无线网休眠,这里面存在很多窄窄的栏,就说明存在问题:反复,频繁出现的唤醒和休眠。
在这里插入图片描述
如果出现大段的红栏和大段的空隙,这代表已经通过降低网络连接提高了性能。用编写代码来分批处理、缓存并延迟这些网络连接工作非常困难,可以使用AndroidAPI替我们完成所有的网络连接工作。

6. 使用JobScheduler

我们将部分任务交给系统决定,因为系统知道什么时间执行最省电,我们的任务是辨别哪些任务可以通过API交给Android任务调度器。
JobScheduler传送门
下面是一个示例,首先需要一个JobService

public class MyJobService extends JobService {
    private static final String LOG_TAG = "MyJobService";

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(LOG_TAG, "MyJobService created");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(LOG_TAG, "MyJobService destroyed");
    }

    @Override
    public boolean onStartJob(JobParameters params) {
        // This is where you would implement all of the logic for your job. Note that this runs
        // on the main thread, so you will want to use a separate thread for asynchronous work
        // (as we demonstrate below to establish a network connection).
        // If you use a separate thread, return true to indicate that you need a "reschedule" to
        // return to the job at some point in the future to finish processing the work. Otherwise,
        // return false when finished.
        Log.i(LOG_TAG, "Totally and completely working on job " + params.getJobId());
        // First, check the network, and then attempt to connect.
        if (isNetworkConnected()) {
            new SimpleDownloadTask() .execute(params);
            return true;
        } else {
            Log.i(LOG_TAG, "No connection on job " + params.getJobId() + "; sad face");
        }
        return false;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        // Called if the job must be stopped before jobFinished() has been called. This may
        // happen if the requirements are no longer being met, such as the user no longer
        // connecting to WiFi, or the device no longer being idle. Use this callback to resolve
        // anything that may cause your application to misbehave from the job being halted.
        // Return true if the job should be rescheduled based on the retry criteria specified
        // when the job was created or return false to drop the job. Regardless of the value
        // returned, your job must stop executing.
        Log.i(LOG_TAG, "Whelp, something changed, so I'm calling it on job " + params.getJobId());
        return false;
    }

    /**
     * Determines if the device is currently online.
     */
    private boolean isNetworkConnected() {
        ConnectivityManager connectivityManager =
                (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        return (networkInfo != null && networkInfo.isConnected());
    }

    /**
     *  Uses AsyncTask to create a task away from the main UI thread. This task creates a
     *  HTTPUrlConnection, and then downloads the contents of the webpage as an InputStream.
     *  The InputStream is then converted to a String, which is logged by the
     *  onPostExecute() method.
     */
    private class SimpleDownloadTask extends AsyncTask<JobParameters, Void, String> {

        protected JobParameters mJobParam;

        @Override
        protected String doInBackground(JobParameters... params) {
            // cache system provided job requirements
            mJobParam = params[0];
            try {
                InputStream is = null;
                // Only display the first 50 characters of the retrieved web page content.
                int len = 50;

                URL url = new URL("https://www.google.com");
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setReadTimeout(10000); //10sec
                conn.setConnectTimeout(15000); //15sec
                conn.setRequestMethod("GET");
                //Starts the query
                conn.connect();
                int response = conn.getResponseCode();
                Log.d(LOG_TAG, "The response is: " + response);
                is = conn.getInputStream();

                // Convert the input stream to a string
                Reader reader = null;
                reader = new InputStreamReader(is, "UTF-8");
                char[] buffer = new char[len];
                reader.read(buffer);
                return new String(buffer);

            } catch (IOException e) {
                return "Unable to retrieve web page.";
            }
        }

        @Override
        protected void onPostExecute(String result) {
            jobFinished(mJobParam, false);
            Log.i(LOG_TAG, result);
        }
    }
}

然后Activity的Button模拟触发多个任务并交给JobService来处理。

public class FreeTheWakelockActivity extends ActionBarActivity {
    public static final String LOG_TAG = "FreeTheWakelockActivity";

    TextView mWakeLockMsg;
    ComponentName mServiceComponent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_wakelock);

        mWakeLockMsg = (TextView) findViewById(R.id.wakelock_txt);
        mServiceComponent = new ComponentName(this, MyJobService.class);
        Intent startServiceIntent = new Intent(this, MyJobService.class);
        startService(startServiceIntent);

        Button theButtonThatWakelocks = (Button) findViewById(R.id.wakelock_poll);
        theButtonThatWakelocks.setText(R.string.poll_server_button);

        theButtonThatWakelocks.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                    pollServer();
            }
        });
    }

    /**
     * This method polls the server via the JobScheduler API. By scheduling the job with this API,
     * your app can be confident it will execute, but without the need for a wake lock. Rather, the
     * API will take your network jobs and execute them in batch to best take advantage of the
     * initial network connection cost.
     *
     * The JobScheduler API works through a background service. In this sample, we have
     * a simple service in MyJobService to get you started. The job is scheduled here in
     * the activity, but the job itself is executed in MyJobService in the startJob() method. For
     * example, to poll your server, you would create the network connection, send your GET
     * request, and then process the response all in MyJobService. This allows the JobScheduler API
     * to invoke your logic without needed to restart your activity.
     *
     * For brevity in the sample, we are scheduling the same job several times in quick succession,
     * but again, try to consider similar tasks occurring over time in your application that can
     * afford to wait and may benefit from batching.
     */
    public void pollServer() {
        JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
        for (int i=0; i<10; i++) {
            JobInfo jobInfo = new JobInfo.Builder(i, mServiceComponent)
                    .setMinimumLatency(5000) // 5 seconds
                    .setOverrideDeadline(60000) // 60 seconds (for brevity in the sample)
                    .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) // WiFi or data connections
                    .build();

            mWakeLockMsg.append("Scheduling job " + i + "!\n");
            scheduler.schedule(jobInfo);
        }
    }
}

关于电量优化Google官方也发布了一些文章

Android Developers 传送门

Android 进阶——性能优化之电量优化全攻略及实战小结(二) 性能优化之电量优化全攻略及实战小结 阅读详情

相关推荐

Android性能优化之电量篇

Google近期在Udacity上发布了Android性能优化的在线课程,分别从渲染,运算与内存,电量几个方面介绍了如何去优化性能,这些课程是Google之前在Youtube上发布的Android性能优化典范专题课程的细化与补充。 下面是电量篇章的学习笔记,部分内容与前面的性能优化典范有重合,欢迎大家一起学习交流! 1)Understanding Battery Drain 手机各个

xjbclz的专栏 639

Android性能优化系列之电量优化

开启无线模式这个过程非常耗电,那么硬件这块为了防止频繁开启关闭耗电,采取了一个无奈的办法,会在一个小段时间内保持开启模式,防止短时间内还有数据包需要接收,也就是图中的Keep Awake的那一段。解决上面的问题,正确的方式可能是使用非精准定时器。电量消耗的计算与统计是一件麻烦而且矛盾的事情,记录电量消耗本身也是一个费电量的事情,随着Android开的性能要求越来越高,电量的优化,也显得格外重要,一个耗电的应用,用户肯定会毫不犹豫的进行卸载,所以本篇博客,我们一起来学习Android性能优化之电量优化。

Gaga246的博客 2145

基于大模型的急性重症胰腺炎全流程预测与诊疗方案研究

本研究构建了基于大模型的急性重症胰腺炎(SAP)全流程预测与诊疗系统,实现了从术前风险评估到术后康复管理的精准诊疗闭环。通过整合临床信息、实验室检查和影像学等多源数据,模型在测试集上预测准确率达X%,AUC为X,显著优于传统评分系统。研究创新性地将预测结果应用于手术方案制定、麻醉决策、并发症防控及个性化护理,形成智能化诊疗方案。验证结果显示模型具有良好的稳定性和临床适用性,同时配套的健康教育体系提升了患者自我管理能力。尽管存在样本局限性和模型可解释性等不足,该研究为SAP的精准诊疗提供了新范式,未来可通过扩

嵌入式毕设/课设资料清单(速查手册·文档模板·题库,持续更新)→ 见最新文章 1115

Android电量/功耗优化指南

电能 = 电压 * 电流 * 时长模块电量(mAh) = 模块电流(mA) * 时长(h)系统电量优化红线规则华为电量优化红线规则。

主营Android,副营Flutter、前端 4009

深入解析TOM模块的PWM输出与ADC触发机制:从配置到DMA数据传输

本文深入解析了TOM模块在嵌入式系统中的核心应用,详细阐述了如何配置其PWM输出功能,并实现与ADC模块的硬件触发同步。重点介绍了通过DMA机制高效传输ADC采样数据的完整流程,涵盖时钟配置、工作模式选择、引脚映射及联调实战,为电机控制、数字电源等实时系统提供了一套硬件自动化的高效解决方案。

weixin_29227585的博客 367

Zemax非序列模式新手入门:从零搭建一个抛物面反射镜系统(含灯丝光源与探测器设置)

本文详细介绍了如何在Zemax非序列模式下从零搭建抛物面反射镜系统,包括灯丝光源配置、反射镜建模和探测器设置等关键步骤。通过实战指南,帮助光学设计新手快速掌握非序列模式的应用技巧,特别适合处理复杂光线传播场景如反射镜系统和杂散光分析。

weixin_28717431的博客 436

Android性能优化之电量优化

1.电量优化 电量优化首先我们要想到怎么去优化,要优化就要分析什么功能以及那些操作最耗电。1.1 Battery Historian Google提供了一个开源的电池历史数据分析工具 – Battery Historian。喜欢的同学可以去学习。Google在Udacity上发布了Android性能优化的在线课程。1.1.1 安装 根据Battery Historian在github上的rea

问心 918

COMSOL模拟CO2驱替CH4:多物理场耦合建模与工程应用详解

在非常规天然气开发与碳封存工程中,多孔介质内的渗流、吸附与岩石变形相互耦合,使得CO2驱替CH4的产能预测和CO2封存评估无法仅靠经验公式完成。以达西定律描述裂隙流动、以扩展Langmuir方程刻画竞争吸附、用应力-吸附-渗透率关系关联煤岩变形,是多物理场耦合数值模拟的核心路径。COMSOL Multiphysics凭借内置渗流、固体力学与组分传递接口,能够将这些机制整合为可参数化扫描的仿真模型,为注气压力、井距、渗透率演化等方案设计提供量化依据。围绕CO2驱替CH4模拟的建模流程、参数取法与结果判读,可形

weixin_29574585的博客 160

Android性能优化:从内存到电量

本文从内存管理和电量消耗两个方面,详细阐述了Android性能优化的方法。通过检测和修复内存泄漏、优化内存复用与缓存、监测和评估电量消耗、采用电量节省策略等手段,可以有效提升应用的性能和用户体验。在实际开发过程中,开发者应关注这些优化方法,并根据具体场景灵活运用。在未来,Android性能优化将继续是开发者关注的焦点,期待更多高效、实用的优化技术出现。持续关注性能优化工具:随着技术的发展,性能优化工具也在不断更新,开发者应关注并使用最新的工具。深入研究性能优化技术。

2501_92487231的博客 423

微信小程序开发:实现地图导航功能

其中,id用于调用地图组件,latitude和longitude表示地图的中心点坐标,markers表示地图中的标记点,covers表示地图中的覆盖物,polyline表示地图中的折线图,show-location表示是否显示当前定位点,bindregionchange表示移动地图时触发的事件。其中,id表示标记点的唯一标识,latitude和longitude表示标记点的坐标,title表示标记点的名称,iconPath表示标记点的图标路径,width和height表示标记点的宽度和高度。

吃不胖. 8917

YOLOv8改进 | 细节涨点篇 | DySample一种超级轻量的动态上采样算子(效果完爆CARAFE)

本文给大家带来的改进机制是一种号称超轻量级且有效的动态上采样器——DySample。与传统的基于内核的动态上采样器相比,DySample采用了一种基于点采样的方法,相比于以前的基于内核的动态上采样器,DySample具有更少的参数、浮点运算次数、GPU内存和延迟。此外,DySample在包括语义分割、目标检测、实例分割、全景分割和单目深度估计在内的五个预测任务中,性能均优于其他上采样器(截至目前最有效的上采样算子)。

Snu77的博客 1万+

【Android】性能优化:电量消耗统计

电量的消耗和使用对于移动设备非常重要,一项调查问卷显示,电池的容量和寿命是手机最重要的营销点:所谓“the one thing that you can't do without”。 硬件 从硬件的角度看,Android电量的消耗主要来自屏幕,CPU,网络设备和各样的传感器:指纹,亮度,温湿度,陀螺仪,加速器等等。通常情况下,屏幕是耗电量最大的模式。一般来讲,Android设备的屏幕主要分...

小魏的修行路 6761

矩阵奇异值分解算法(SVD)的导数 / 灵敏度分析

设矩阵X∈Rm×nX∈Rm×nXUΣV⊤XUΣV⊤U∈Rm×mU∈Rm×m为左奇异向量矩阵;V∈Rn×nV∈Rn×n为右奇异向量矩阵;Σdiag⁡σ1σ2σrΣdiagσ1​σ2​σr​为奇异值对角阵(rrank⁡XrrankX我们关心:当XXX发生微小扰动dXdX时,UΣVUΣV如何变化?dXdUΣV⊤dX。

qq_36812406的博客 1750

Android性能优化:内存管理与电量消耗

本文详细阐述了Android性能优化中的内存管理和电量消耗问题。通过检测和修复内存泄漏、优化内存缓存、优化网络请求、降低CPU使用率以及优化图片资源和代码,可以有效提升应用性能,降低电量消耗。这些优化方法对于提高用户体验具有重要意义。在未来,Android性能优化将继续是开发者关注的焦点。随着技术的发展,新的优化工具和方法将不断涌现。开发者需要不断学习和实践,以提升自己的优化能力。同时,也建议开发者关注用户反馈,从用户的角度出发,持续优化应用性能。

2501_91460574的博客 321

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Android 性能优化 (十一) 电量优化全解析 秒变大神

Android 性能优化 (一)APK高效瘦身 http://blog.youkuaiyun.com/whb20081815/article/details/70140063 Android 性能优化 (二)数据库优化 秒变大神 http://blog.youkuaiyun.com/whb20081815/article/details/70142033 Android 性能优化(三)布局优化 秒变大神 ...

深南大盗的博客 1228

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Android性能优化:内存管理与电量优化

本文详细阐述了 Android 性能优化中的内存管理和电量优化两个方面。内存泄漏的检测与修复以及内存优化策略,可以有效提高应用的性能;而 CPU 使用优化和网络优化,则有助于降低电量消耗。通过正确实施这些优化措施,开发者可以构建更加高效、流畅的 Android 应用,满足用户对性能和电量的需求。在未来,随着技术的不断发展,Android 性能优化仍将是开发者需要关注的重要领域。持续关注新的优化技术和工具,提升开发效率。深入研究用户行为,针对不同场景进行优化。方面具体措施内存管理。

2501_92489014的博客 481

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

安卓性能优化-电量优化建议

现在安卓设备,很多都会有电量使用监控软件,可以查看设备上应用的耗电量情况。虽然有很多手机号称超长待机,但是他们也只是在手机静默状态下的测试数据,应用启动后的一些操作几乎都会不同程度的有一个电量消耗小高峰。比如唤醒屏幕、频繁的网络请求、复杂的cpu运算、传感器的监听、后台的长时间运行等等。如果你的应用一直保持着这种亢奋状态,那么它对电量的消耗是非常可怕的。作为用户,肯定不希望刚充满的电,一会儿就告罄...

lotty_wh的博客 958

Android性能优化—Android电量优化

手机耗电的根本原因 是软件 电能 电能(J) = 电功率P(W) * 时间t(s) 电功率P(W) = 电压U(V) * 电流I© 电量Q© = 电流I(A) * 时间t(s) 电池说明代表的含义是什么? mAh表示电量,Wh表示电能,即在提供稳定电压3.7V的情况下,可以提供稳定电流1700mA一个小时,即我们在测试的过程中给手机提供恒定的电压,只需获取电流值就可以量化手机的功耗 如何获取电量的值 测试方法 通过Android API获取 re

yzpbright的博客 670
上一篇: Android性能优化——运算
下一篇: 计算机网络——物理层(一)
PdKingLiu
博客等级 码龄9年 89粉丝 92原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值