DEV Community

suesitran
suesitran

Posted on

Flutter — Interactive Diary — A developer diary #13

Create Connectivity service

To check device connectivity, there’s a package that works perfectly for that purpose: connectivity_plus.

It’s also a Flutter Favourite package, so I assume it’s safe to use right now. However, I’m being skeptical about using 3rd party directly in the app, so I’m going to wrap it inside my ConnectivityService again.

Connectivity research

The idea of ConnectivityService is only to check if the device is having any form of connection, be it wifi, mobile, bluetooth or ethernet.

For a mobile device, connecting to Wifi or Mobile can suggest that there’s internet connection on the device. However, when I was playing with my Android phone, I realised that it has Bluetooth tethering, and with little search on Google, and I came across this page. It means there can be internet sharing using Bluetooth connection. Therefore I added Bluetooth into my list of online status.

And although it’s not common among mobile users, but connecting mobile device to ethernet to have internet access is also possible. Here is an article how to connect your mobile to ethernet. So as tricky as it can be, ethernet is 1 of my online status as well.

That’s all for connectivity research. Now let’s do code plan.

Code plan

The first need of this service is to know at any point of time, is the device having any form of connectivity? To do this, I need a boolean that returns true/false, in which, true means there is connectivity, and false means there’s no connectivity.

Next, in some cases, I’ll also need to be informed immediately when my device loses connectivity, or regains connectivity. So I’ll need a Stream<bool> which will send true/false value, true means there is connectivity, and false means there’s no connectivity.

That’s simple. Let’s code.

Coding time

First, I’ll need to create a boolean to check if device is currently having any connectivity at all. Because checking connectivity from connectivity_plus will return a Future, therefore my boolean also needs to be a Future.

Secondly, I need a Stream<bool>, so there it is, a Stream<bool>.

First, draft out the expected result

Now I need to do the actual implementation of _checkConnectivity(), and _connectivityChange.

But first, I need an instance of Connectivity from connectivity_plus package.

Define instance of Connectivity

The optional Connectivity? here is to be used later in test with a mocked instance of Connectivity class.

Then, let’s look at _checkConnectivity(). The idea of this method is to return a boolean, with false means no connectivity, and true means otherwise, so the code is as simple as this.

Implementation of _checkConnectivity()

The reason optional ConnectivityResult? is added is because this method will be reused later with ConnectivityResult value.

Now, let’s look at _connectivityChange. This is actually a StreamController, which can emit a new value to the Stream attached to it.

StreamController to emit changes to onConnectivityChange

There are multiple connectivity types, but I only want to emit changes when connectivity is from connected to none. I do not want to be informed when connectivity is switching from 1 type to another. Therefore I need a boolean to know the current connectivity status, and will emit change if and only if connectivity is change from connected to none.

To do this, I’ll create a boolean for current connectivity, and check connectivity as soon as the instance is created.

Create boolean to keep track of current connection status

Now it’s time to work on the connectivity change. Connectivity class has a Stream that emit ConnectivityStatus. I will just need to listen to this stream, and check when connection change from connected to none, and emit the change when connection status is changed. I’ll do this in the constructor as well, so the constructor becomes this.

Update constructor to listen to changes in onConnectivityChange

And last step, add implementation of _handleConnectivityChange().

Implementation of  raw `_handleConnectivityChange()` endraw

That’s it. Now, test time.

Test time

To test my ConnectivityService, I’ll need to mock the behaviour of Connectivity class. To do this, I’ll need to use Mockito package, as well as build_runner package.

Add mockito and build_runner packages

These packages are added under dev_dependencies because I only need them during development.

The test class name is nartus_connectivity_test.dart, which is the same file name as the class I want to test, and add suffix _test to it. This is to make it easier to find which class this test is about, and also easier for me to write script later if I need to.

To generate the mocks to classes I need, I add this annotation right above the main method

Annotation to generate Mock

After that, I need to run following command to generate the mock file.

Run build runner command to generate mock file

This command is included in scripts/generate_dependencies.sh, so my actual command is

Run script to generate mock files

There are pro and con in doing it this way. Pro is that it saves time for me to remember the command to run, but con is that it takes longer time, because this script will run in all packages. As I add more packages to the project, this script will take longer time to run. Maybe I need to find a better way to do this.

Anyway, back to the test. Now I have the mock file generated, I can import it into my test, and start making an instance of the mock, and start testing.

Create instance of MockConnectivity

In each of the test, it’s always a good practice to give the condition of the test (GIVEN), then action to do (WHEN), and the expected result (THEN). This way, it’s clear what the test is about.

In the first test, I want to ensure that isConnected will return false if current connectivity is none, so I give the description of the test as

given current connectivity is none, when get isConnected, then return false

isConnected returns false when connectivity is none

Similarly, I need to test with other connectivity types as well: bluetooth, wifi, mobile, ethernet.

Next, I’ll need to test the connectivity stream. I know that when connectivity is changed from none to other connectivity type, I expect there is a value emit to my stream. So the description of this test will be

given current connectivity is none, when connectivity change to mobile, then emit true to connectivity change stream

Test when connectivity changes from none to mobile

Then I continue to test the same scenario with other connectivity types: wifi, bluetooth, ethernet.

Another case to test is when changing between these connectivity type, there should be no value emit to my stream. So the description of the test will be

given current connectivity is mobile, when connectivity change to bluetooth, then do not emit changes to stream

Test to ensure there’s no value emit to stream when connectivity switch from 1 to another

Lastly, I need to test that when there are multiple connectivity change happens, but onConnectivityChange will only emit 1 change when connectivity is changed to none.

given connectivity switches multiple times, when listening on stream, then only emits value when Connectivity change to none

Test to ensure that there is only 1 value emit when connectivity changes from connected to none

And that’s it, my ConnectivityService is done.


That’s all for today. If you like my article, please follow for more tips.

Top comments (0)