/ beginner

Tracking your Battery

Occasionally you need to know what the battery level is the device. This is pretty simple with the battery package from the flutter plugins.

Download

Visit the GitHub repository to clone the source for this application.

This code was tested with Flutter 0.5.1

Setup

We're only going to cover the actual interaction with the battery package and not the rest of the app. As such, we'll start at the starting_point tag in the repo. The app and the battery display are all built by this point and just waiting for the updates to happen.

Once the code is checked out, just run git checkout starting_point to update your local copy to the tag.

Our finished version is tagged as with_battery

The app already has a basic battery icon that shows the charging state and charge level. It is initialized to a default state of charging with 75% charge level. We're going to make these values update dynamically.

We will use the variables _batteryState to store the current charging state, and _batteryLevel to store the current charge level.

The Code

Step 1: Import the package

The following steps were already done for this tag, but we're going to cover them quickly.

To add the plugin to our app, we need to add the following line to our pubspec.yaml under "dependencies:"

  battery: ^0.2.2

If you're using VSCode or Android Studio, they should either prompt your to updater your dependencies or just do it automatically. If you're not, then run flutter packages get to download our new dependencies.

Next, we need to add the import to the top of our lib/main.dart file so that our code can use the new dependency.

import 'package:battery/battery.dart';

Step 2: Add in the callback handling

In lib/main.dart, we need to update our state handling to account for the new library. All of the following code will be added inside the _BatteryLevelPageState class.

Step 2.1: Create a plugin instance

This is pretty straight forward, but we need to create an instance of the plugin in our code so that we can interact with it.

Fun Fact: The plugin uses a factory to implement the singleton pattern.

Add the following line of code to the top of the _BatteryLevelPageState class.

final Battery _battery = Battery();

We make this variable final because we never intend to reassign it to a new value. The name, _battery, is prefixed with an underscore to denote that the variable is "private".

Step 2.2: Set up our listeners

The battery provides two asynchronous properties that we are going to interact with. First batteryLevel which provides us with a 0 to 100 representation of the current charge level. Second onBatteryStateChanged that will inform us when the charging state of the battery changes or the battery level percentage has changed.

In the initState method of _BatteryLevelPageState, remove the current initializers for _batteryLevel and _batterystate and add the following code instead:

    _battery.batteryLevel.then((level) {
      this.setState(() {
        _batteryLevel = level;
      });
    });

    _battery.onBatteryStateChanged.listen((BatteryState state) {
      _battery.batteryLevel.then((level) {
        this.setState(() {
          _batteryLevel = level;
          _batteryState = state;
        });
      });
    });

Our first block of code is accessing the batteryLevel future. We're using .then to wait for the value to be available, then updating our state to store that value.

Our second block is roughly equivalent, except that onBatteryStateChanged is a stream that will supply us a new value periodically. We listen for any of these changes, re-query the current battery level, then update our state with both new values.

And now, it's beautiful:
battery_state

Step 3: Finishing up

All the heavy lifting was done already to make the _batteryState and _batteryLevel values be displayed. When we call setState, we are notifying the widget that it needs to repaint with new values. Then the magic all happens here:

              child: CustomPaint(
                painter: _BatteryLevelPainter(_batteryLevel),
                child: _batteryState == BatteryState.charging ? Icon(Icons.flash_on) : Container(),
              ),

We have a CustomPainter to draw the battery and it's charge level. Then, if we're charging, we tell the painter to draw a lightning icon inside itself.

Step 4: Caveats

This is really only testable in an emulator with Android. The iOS emulators do not support changing or handling the battery state.

Step 5: Credits

I borrowed heavily from the battery_indicator plugin for the custom painter for drawing the shape of the battery.

If you don't feel like drawing your own, the plugin above is easily customized to fit your needs.

Brian Armstrong

A web application developer with 15+ years programming experience. Flutter evangelist, React.js enthusiast.

Read More