How to Optimize Android Battery Usage

New Media Manager

Click on the top “Programmer Co-Reading“, select “Top Public Account”

At critical moments, deliver first!

How to Optimize Android Battery Usage

How to Optimize Android Battery Usage

Calculating and counting battery consumption is a troublesome and contradictory task. Recording battery consumption itself is also a power-consuming activity. As the performance requirements of Android increase, battery optimization becomes particularly important. An application that consumes too much power will surely be uninstalled by users without hesitation. Therefore, in this blog, we will learn about battery optimization as part of Android performance optimization.

How is power consumption generated?

Power consumption occurs when the screen is turned on, and all actions requiring CPU/GPU work will wake the screen and consume power. This is different from applications waking the device.

(1) Wake the screen

When the user wakes the screen, it means that the system components need to start working, and the interface needs to begin rendering.

Power consumption in standby mode:

How to Optimize Android Battery Usage

After using and waking the screen:

How to Optimize Android Battery Usage

When the device is awakened from sleep by an application, a peak in battery usage occurs.

After the work is completed, the device will actively enter sleep mode, which is very important. Keeping the screen awake for a long time when not in use or rarely used will quickly drain the battery.

(2) Cellular wireless

How to Optimize Android Battery Usage

From this image, we can see that using cellular wireless generates several peaks:

  1. When the device sends data over wireless, a peak occurs due to hardware usage,

  2. Next, there is a high value representing the power consumed when sending data packets,

  3. Then, receiving data packets will also consume a lot of power, showing a peak as well.

Enabling wireless mode is very power-consuming. To prevent frequent on/off cycles from consuming power, hardware adopts a workaround to keep the mode on for a short period, preventing short-term data packets from needing to be received, as shown in the Keep Awake section of the image.

How to analyze battery usage?

(1) Battery data collection

Devices running Android 5.0 and above allow us to dump battery usage statistics using adb commands.

1. Since battery statistics are continuous, reset the statistics before testing the app. Connect the device and execute the command in the command line:

$ adb shell dumpsys batterystats –reset

Battery stats reset.

2. Disconnect the test device and operate the app to be tested.

3. Reconnect the device and use adb commands to export the relevant statistics:

// This command continuously records output. Press Ctrl+C to stop recording.

$ adb bugreport > bugreport.txt

The exported statistics are stored in bugreport.txt. At this point, we can use tools to visualize battery consumption.

Note, the official SDK documentation export method is:

adb shell dumpsys batterystats > batterystats.txt

Use Python historian.py batterystats.txt > batterystats.html to view data

This is the old version of battery-historian usage. Currently, Battery Historian has been updated to version 2.0, and it is recommended to use the bugreport method to export data analysis to see more information.

(2) Battery analysis tool Battery Historian

Tool open-source address: https://github.com/google/battery-historian

According to the introduction on GitHub, there are two ways to install the Battery History tool:

1. Install via Docker environment. (Requires VPN)

Docker only supports Windows 10

How to Optimize Android Battery Usage

The command and address on GitHub are as follows:

docker — run -p <port>:9999 gcr.io/android-battery-historian:2.1 –port 9999

2. Install by compiling the source code on GitHub.

(1) Install GO environment:

1. Download

Download directory: https://golang.org/doc/install

https://golang.org/doc/install?download=go1.7.3.windows-amd64.msi

How to Optimize Android Battery Usage

2. Install GO

How to Optimize Android Battery Usage

3. Configure GOROOT and GOPATH

a. GOROOT indicates where to find the Go packages installed on your system, so configure it to the GO installation directory

How to Optimize Android Battery Usage

b. GOPATH can be simply understood as the project directory, so create a path for your GO project

How to Optimize Android Battery Usage

c. Finally, configure the environment variable to include the bin directory of Go in the path environment variable

d. Check if Go is installed successfully by opening the command line and typing Go version

How to Optimize Android Battery Usage

(2) Install Git

1. Click to download【Download】; (https://git-scm.com/

2. Follow the steps to install;

3. After installation, check: type git version in the command line

How to Optimize Android Battery Usage

(3) Install Python

1. Click to download【Download】, note that it only supports python2.7 (https://www.python.org/

2. After installation;

3. Configure environment variables, add the Python installation path to the Path variable

4. Type command python –V (note the capital V) to check if it is installed successfully

How to Optimize Android Battery Usage

(4) Install Java environment

1. Click to download: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

2. Complete the installation.

(5) Download the Battery Historian source code and run it

Type the command line go get -d -u github.com/google/battery-historian/…

Download to the GOPATH configuration directory

1. Enter the $GOPATH/src/github.com/google/battery-historian directory

$ cd $GOPATH/src/github.com/google/battery-historian

2. Run Battery Historian

1) go run setup.go

$ go run setup.go

Wait a few minutes or about 10 minutes. If it still fails to download, you can manually download as follows

Download【closure-library】and【closure-compiler】and【flot-axislabels】, unzip and place them in the GOROOT directory under the third_party folder ../battery-historian; create them manually if they do not exist

2)go run cmd/battery-historian/battery-historian.go

$ go run cmd/battery-historian/battery-historian.go [–port <default:9999>]

Using battery-historian

Data preparation

The battery-historian tool requires using Battery History from the bug report

1. First disconnect the adb service, then start the adb service

adb kill-server This step is very important because when we record battery usage during development, many things may conflict. To be safe, we restart adb.

adb devices will automatically connect and find the phone. Of course, you can also use adb start-server

2. Reset battery data collection

We need to use the following command to enable battery data collection and reset:

adb shell dumpsys batterystats –enable full-wake-history

adb shell dumpsys batterystats –reset

The above operation is equivalent to an initialization operation. If not done, there will be a lot of interference data, which will be painful to look at. Then directly unplug the data line (to prevent interference from charging and discharging data), and now perform some tests, either manually or running some automated cases. After a while, reconnect the phone to confirm that adb is connected, and run the following command to save the bug report information to a txt document,

adb bugreport > bugreport.txt

Or you can use the following command:

adb shell dumpsys batterystats > batterystats.txt

adb shell dumpsys batterystats > com.example.android.demo.app > batterystats.txt

Adding the package name can limit the output data to what we want to check.

However, the readability of this txt data is not strong. Next, we will use the battery-historian tool.

Analyze data

How to Optimize Android Battery Usage

Meaning of various parameters

First, we find the Battery History data section in bugreport.txt similar to the information below:

DUMP OF SERVICE batterystats:

Battery History (2% used, 5980 used of 256KB, 45 strings using 2592):

0 (9) RESET:TIME: 2015-03-05-15-21-56

0 (2) 100 c0900422 status=discharging health=good plug=none temp=200 volt=4167 +running +wake_lock +sensor +screen data_conn=edge phone_signal_strength=great brightness=medium proc=u0a15:”android.process.acore”

0 (2) 100 c0900422 proc=u0a7:”com.android.cellbroadcastreceiver”

0 (2) 100 c0900422 proc=u0a53:”com.android.gallery3d”

You can find corresponding information in the html from bugreport.txt.

Now let’s analyze the meaning of each index:

Horizontal axis

How to Optimize Android Battery Usage

The above 10, 20 represent seconds, meaning that it is on a one-minute cycle, and at the 60th second it becomes 0. The horizontal axis represents a time range. In our example, the data collected is from the reset point to the time of obtaining the bug report content. We have collected data for how long, and the information is also indicated under the chart. (According to feedback from others, this coordinate interval changes with the length of time, so it should be based on your actual situation. This zoom level can be adjusted, as shown in the image below:)

How to Optimize Android Battery Usage

Vertical axis

How to Optimize Android Battery Usage

Battery optimization

Track Battery Status & Battery Manager

We can use the following code to get the current charging status of the phone:

// 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);

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!”);

}

The above example demonstrates how to immediately obtain the charging status of the phone. After obtaining the charging status information, we can optimize certain parts of the code accordingly. For example, we can determine that certain power-consuming operations should only be executed when the phone is in AC charging status.

/** * This method checks for power by comparing the current battery state against all possible * plugged in states. In this case, a device may be considered plugged in either by USB, AC, or * wireless charge. (Wireless charge was introduced in API Level 17.) */

private boolean checkForPower() {

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.

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);

}

Screen wake

Sometimes we need to change the default state of the Android system: for example, when playing games we need to keep the screen on, while for some download operations, we do not need the screen to stay on, but we need the CPU to keep running until the task is completed.

The best way is to use the FLAG_KEEP_SCREEN_ON flag in the Activity.

getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

Another way is to use the android:keepScreenOn attribute in the layout file:

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”

android:layout_width=”match_parent”

android:layout_height=”match_parent”

android:keepScreenOn=”true”>

</RelativeLayout>

android:keepScreenOn = “true” has the same effect as FLAG_KEEP_SCREEN_ON. The advantage of using code is that it allows you to turn off the screen where needed.

Note: Generally, there is no need to manually remove the FLAG_KEEP_SCREEN_ON flag, as the window manager will manage the operations of the program entering the background and returning to the foreground. If it is indeed necessary to manually clear the always-on flag, use getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

Wakelock and Battery Drain

Suppose your phone has a lot of social applications installed, even if the phone is in standby mode, these applications will frequently wake the phone to check for new data synchronization. One of the simplest ways to wake the phone is to use the PowerManager.WakeLock API to keep the CPU running and prevent the screen from dimming or shutting off. This allows the phone to be woken up, perform work, and then return to sleep mode. Knowing how to obtain a WakeLock is easy, but it is also very important to release it in a timely manner. Improper use of WakeLock can lead to severe errors. For example, if the return time for network request data is uncertain, what should only take 10s might end up waiting for 1 hour, wasting battery power. This is why it is crucial to use the wakelock.acquire() method with a timeout parameter.

wake_lock is mainly relative to the system’s sleep state, meaning that my program has added this lock to the CPU, so the system will not sleep. The purpose of this is to fully cooperate with the operation of our program. In some cases, if this is not done, problems may arise, such as WeChat and other instant messaging heartbeat packets stopping network access shortly after the screen turns off. Therefore, WeChat uses a lot of wake_lock.

wake_lock: two types of locks, one is a counting lock; non-counting lock (if locked many times, only one release is needed to unlock)

Wake locks can be divided into and identified as four types of user wake locks:

How to Optimize Android Battery Usage

Since API level 17, FULL_WAKE_LOCK has been deprecated. It is recommended to use FLAG_KEEP_SCREEN_ON instead.

Add wake lock permission:

<uses-permission android:name=”android.permission.WAKE_LOCK” />

Directly use the wake lock:

PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);

WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,”MyWakelockTag”);

wakeLock.acquire();

Note: When using this class, you must ensure that acquire and release appear in pairs. Otherwise, when our business no longer requires it, and the CPU is in a wake state, it will consume excess power.

However, simply setting a timeout is not enough to solve the problem. For example, how long should the timeout be set? When should retries occur? To solve these issues, the correct approach may be to use a non-precise timer. Typically, we set a time to perform a certain operation, but dynamically modifying this time may be better. For example, if another program needs to wake up 5 minutes later than your set time, it is better to wait until that time, allowing both tasks to proceed together. This is the core working principle of a non-precise timer. We can schedule tasks, but if the system detects a better time, it can delay your task to save battery consumption.

JobScheduler

The purpose of JobScheduler is to batch process some non-urgent tasks at a more suitable time.

Customize a Service class that inherits from JobService

public class JobSchedulerService extends JobService{

private String TAG = JobSchedulerService.class.getSimpleName();

@Override

public boolean onStartJob(JobParameters jobParameters) {

Log.d(TAG, “onStartJob:” + jobParameters.getJobId());

if(true) {

// JobService runs on the main thread. If we need to handle time-consuming business logic, we should start a separate thread to handle it and return true,

// When the given task is completed, call jobFinished(JobParameters params, boolean needsRescheduled) to inform the system.

// Assume starting a thread to download a file

new DownloadTask().execute(jobParameters);

return true;

}else {

// If only simple logic is executed in this method, return false

return false;

}

}

/**

* For example, if the constraints we set for the service require it to run under WIFI, and during the task execution process, WIFI disconnects, the system

* will notify us to stop running through the onStopJob() callback. Normally, this method will not be called back

*

* @param jobParameters

* @return

*/

@Override

public boolean onStopJob(JobParameters jobParameters) {

Log.d(TAG, “onStopJob:” + jobParameters.getJobId());

// If you want the service to run again when the specified conditions are met, return true; otherwise, return false

return true;

}

class DownloadTask extends AsyncTask<JobParameters, Object, Object> {

JobParameters mJobParameters;

@Override

protected Object doInBackground(JobParameters… jobParameterses) {

mJobParameters = jobParameterses[0];

// For example, we handle a download task here

// or handle some complex computation logic

//…

try {

Thread.sleep(30*1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

return null;

}

@Override

protected void onPostExecute(Object o) {

super.onPostExecute(o);

// If true is returned in onStartJob(), after processing is complete, be sure to call jobFinished() to inform the system that it is done,

// If the service needs to be rescheduled, return true; otherwise, return false

jobFinished(mJobParameters, false);

}

}

}

Remember to configure the Service in the Manifest file

<service android:name=”.JobSchedulerService” android:permission=”android.permission.BIND_JOB_SERVICE”/>

Create a work plan

public class MainActivity extends Activity{

private JobScheduler mJobScheduler;

private final int JOB_ID = 1;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.mai_layout);

mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE );

// Set constraints for triggering the service using JobInfo.Builder, at least one condition must be set

JobInfo.Builder jobBuilder = new JobInfo.Builder(JOB_ID, new ComponentName(this, JobSchedulerService.class));

// Set periodic trigger, tasks will run every three seconds

jobBuilder.setPeriodic(3000);

// Set single scheduled trigger, set to trigger three seconds later. This is incompatible with setPeriodic(long time),

// and using both functions simultaneously will throw an exception.

jobBuilder.setMinimumLatency(3000);

// Set the condition to trigger if none of the specified conditions are met within the agreed time

// This function is mutually exclusive with setPeriodic(long time), and using both functions will throw an exception.

jobBuilder.setOverrideDeadline(3000);

// Set whether the trigger conditions remain valid after the device restarts

jobBuilder.setPersisted(false);

// Only trigger when the device is in a specific network state.

// JobInfo.NETWORK_TYPE_NONE, can trigger regardless of network; this is the default value;

// JobInfo.NETWORK_TYPE_ANY, trigger when there is a network connection;

// JobInfo.NETWORK_TYPE_UNMETERED, trigger in non-cellular networks;

// JobInfo.NETWORK_TYPE_NOT_ROAMING, trigger in non-roaming networks;

jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);

// Set to trigger when the phone is charging

jobBuilder.setRequiresCharging(true);

// Set to trigger when the phone is idle

jobBuilder.setRequiresDeviceIdle(true);

// Obtain the JobInfo object

JobInfo jobInfo = jobBuilder.build();

// Start scheduling the task, it will return a status code

//JobScheduler.RESULT_SUCCESS, success

//JobScheduler.RESULT_FAILURE, failure

if (mJobScheduler.schedule(jobInfo) == JobScheduler.RESULT_FAILURE) {

// Task scheduling failed

}

// Stop the specified JobId service

mJobScheduler.cancel(JOB_ID);

// Stop all job services

mJobScheduler.cancelAll();

}

How to Optimize Android Battery Usage

  • From:CSDN-Ma Yunlong

  • http://blog.csdn.net/u012124438/article/details/74617649#t3

  • Programmer Co-Reading organized and published, please contact the author for authorization

How to Optimize Android Battery Usage

How to Optimize Android Battery Usage[Click to become an Android expert]

Leave a Comment