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>
.
Now I need to do the actual implementation of _checkConnectivity()
, and _connectivityChange
.
But first, I need an instance of Connectivity
from connectivity_plus
package.
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.
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.
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.
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.
And last step, add implementation of _handleConnectivityChange()
.
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.
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
After that, I need to run following command to generate the mock file.
This command is included in scripts/generate_dependencies.sh
, so my actual command is
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.
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
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
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
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
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)