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
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:
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
HttpAn 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.
- Login Request
- API Service
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;
}
}
export const service = (requestData) => fetch(requestData.url,{
method: 'POST',
body: JSON.stringify(requestData.data),
})
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());
}