Skip to main content
Version: Next

Battery Optimization

On Mobile Applications, battery is an important aspect that every mobile developer should take into account while developing an application.

Location Accuracy and Interval

When the application uses current location of device, it is important to not request it unless needed. Especially on Android devices, developer can request for both precise location or coarse ( less precise ) location. Using more precision consumes more battery.

Relevant permission: https://developer.android.com/reference/android/Manifest.permission#ACCESS_FINE_LOCATION

info

When only a specific page requires location in your app, accessing the location at onLoad method will be better since it will be called less. More info is located at the link below:

Page Life-Cycle

Location Start & Stop

Location.start() method will request the current location from the device by interval in the background. It is important to stop requesting location by using Location.stop() method.

Camera

Using camera will consume a lot of battery on the process. Especially embedding a QR reader or Barcode Reader will take more toll on the battery. Consider warning user about battery if such feature is required.

Relevant utility: https://github.com/smartface/sf-extension-barcode

Screen Lock & Brightness

Your application might have a streaming service implemented and that requires screen to be awake and brightness set on max. Those will consume battery and heat up the device. Consider warning user beforehand.

setTimeout & setInterval - Async Task

Async Task
  • setTimeout
  • setInterval
  • asyncTask
  • __SF_MAIN.dispatch

Since Smartface is powered by Javascript, there will be a single thread and that will be a main tread. Those methods mentioned above will run in the background, creating pseudo threads to be queued.

onShow() {
super.onShow();
setInterval(() => console.log, 1000);
}

The snippet above will run every second, until the app is killed. This will drain the battery, since there will be another task running every second. Also, every time the page is opened, it will create another task, creating a memory leak and potentially infinite overhead.

Consider doing this instead:

onHide() {
super.onHide();
clearInterval(this.myInterval);
}

onShow() {
super.onShow();
this.myInterval = setInterval(() => console.log, 1000);
}

This way, your interval value will be cleared when not in use and will not clutter the background thread.

Reference: https://www.w3schools.com/jsref/met_win_clearinterval.asp

Http & XmlHttpRequest

Http

An http client will also create necessary header in the background thread, setting up the app to request http calls from a server. However, created http client will run in the background, resulting in consuming batter.

To overcome this, it is recommended to create as less as http client possible.

scripts/service/login.ts
import { service } from "service";

async function login(username: string, password: string): Promise<void> {
try {
let requestData = {
url: 'example.com/login',
data: {
username: username,
password: password
}
}
await service(requestData);
} catch (err) {
console.error(err);
throw err;
}
}

For all requests based on http://api.mybaseurl.com API, a single http client was used. Creating different http clients for each call will drain the battery.

onMinimize - onMaximize

Application.onMinimize() and Application.onMaximize() will be called each time the application is brought to foreground or hidden to background. It is necessary to consider close any background thread actions by those two method.

State Management

If the project is using a state management tool like Redux or Flux, the developer is bound to use subscribe methods to listen through changes. This methods will create a background process and will not be closed until the application is killed, hence resulting in draining the battery. Consider using subscribe methods like this:

import store from "duck/store"; // Reference: https://redux.js.org/style-guide/style-guide/

onHide() {
super.onHide();
this.unsubscribe();
}

onShow() {
super.onShow();
this.unsubscribe = store.subscribe(() => this.yourRefreshAction());
}