Tutorials
Snippets
Subscribe on Youtube

Provide Battery Information in Flutter

Cover image
Slack
View Code

Like in this tutorial where we provide our network status to the app, we sometimes make decisions on other information as well, a note worthy one being the battery percentage.

In this tutorial we'll build a DeviceInformationSerivce that will provide a stream of Battery Percentage values. The full DeviceInformationService also provides the connection status, along with some other info but we'll only provide the Battery info to keep the tutorial on point.

Setup

We'll start by adding the packages that are required for this functionality.

battery: ^0.3.0+4
provider: ^3.0.0

Then we'll create model class to hold the BatteryInformation.

class BatteryInformation {
  final int batteryLevel;

  BatteryInformation(this.batteryLevel);
}

Implementation

We'll create a DeviceInformationService that will expose a stream that emits the battery level every 5 seconds. We'll provide that stream through a StreamProvider to consume in our UI. We'll start by creating the device_information_service.dart

import 'dart:async';

import 'package:battery/battery.dart';
import 'package:device_information/device_information.dart';

class DeviceInformationService {
  bool _broadcastBattery = false;
  Battery _battery = Battery();

}

We'll create an instance of the battery package class and keep that locally. Then we can go ahead and setup our StreamController and expose the Stream through a property.

  Stream<BatteryInformation> get batteryLevel => _batteryLevelController.stream;

  StreamController<BatteryInformation> _batteryLevelController =
      StreamController<BatteryInformation>();

The function to emit the batteryLevel every 5 seconds will be a future that has a while loop with the condition if _broadcastBattery is true. This will allow us to cancel this broadcast if needed. Create a new function _broadcastBatteryLevel that gets the batteryLevel and emits it over the stream then waits for 5 seconds.

  Future _broadcastBatteryLevel() async {
    _broadcastBattery = true;
    while (_broadcastBattery) {
      var batteryLevel = await _battery.batteryLevel;
      _batteryLevelController
          .add(BatteryInformation(batteryLevel));
      await Future.delayed(Duration(seconds: 5));
    }
  }

We'll also create a stopBroadcast function that we won't use in this tutorial but just to have it in case you want to call it on dispose. To stop services that rely on streams when your app goes into the background you can implement a Lifecycle Manager and call stop in there. We won't cover that in this tutorial.

  void stopBroadcast() {
    _broadcastBattery = false;
  }

Usage

To use this stream throughout the app we will Provide it through a StreamProvider.

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return StreamProvider(
      builder: (BuildContext context) =>
          DeviceInformationService().batteryLevel,
      child: MaterialApp(title: 'Flutter Demo', home: BatteryView()),
    );
  }
}

Note: Services functionality are to be used only from your business logic / view models like this example, not directly from a view. Outside of initialisation. This tutorial won't do that so it can stay on topic

We'll consume the provided information in our UI using the Provider.of call.

class BatteryView extends StatelessWidget {
  
  Widget build(BuildContext context) {
    var batteryInfromation = Provider.of<BatteryInformation>(context);
    return Scaffold(
      body: Center(
        child: Text('Battery Level: ${batteryInfromation?.batteryLevel}'),
      ),
    );
  }
}

Based on the Battery level you can now make decisions in your UI to grey out or hide widgets based on the percentage. To see how to build widgets that reacts to your device's information check out this tutorial. Check out all the other Snippets for more Flutter tutorials.

Slack
View Code