Flutter — Interactive Diary — A developer diary #13
Tags: flutter, interactivediary, programming
Published: 2022-09-27 00:04:29

## Create Connectivity service

To check device connectivity, there’s a package that works perfectly for that purpose: [connectivity_plus](https://pub.dev/packages/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](https://support.google.com/android/answer/9059108?hl=en#zippy=%2Ctether-by-bluetooth). 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](https://au.pcmag.com/networking/86532/how-to-connect-a-phone-or-tablet-to-the-internet-using-an-ethernet-cable). 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/km3ndf0uof97apxdkh4o.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m89wffmeojzrdxyphv6o.png)

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()](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3t123tnv4o7rr90wxpsk.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8giawlrptkirh8cpaokp.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34pplorf17y3xu3ty9ou.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wudufx7mgivfjhb7pa1d.png)

And last step, add implementation of `_handleConnectivityChange()`.

![Implementation of `_handleConnectivityChange()`](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qhqzzzodmk25gdt0f4fw.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuaorxrab37kq39yd2ww.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qcczyd1sun14ujfnpt1y.png)

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

![Run build runner command to generate mock file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xb63z8dfdlhjdbd94ccv.png)

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

![Run script to generate mock files](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v1syeaph23wmp0a9d5tc.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/at1wubywdrmr7ghlkoyw.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8pkufdlqvgaza4dp4dzh.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vz0zn32lyohczhhcnosa.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ipmqu4u6maaev8qt4r3b.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lxs4k48ssnzpsnujl03e.png)

And that’s it, my `ConnectivityService` is done.

---

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