Beyond UI: Flutter + Socket.io : Real-time Communication
Beyond UI: Flutter + Socket.io : Real-time Communication
Real-time communication is the near-simultaneous exchange of information over any type of telecommunications service from the sender to the receiver in a connection with negligible latency… What Is Real-Time Communications? — Vonage.
This post was first published at [Codemagic blog](https://blog.codemagic.io). Codemagic is the developer’s top choice for CI/CD for Android, iOS, Flutter, and React Native projects.”
In an age where speed is critical to survival, in a time when there is a need to deliver data and have it go to/from users instantly. There are a couple of ways to achieve this and making multiple network requests doesn’t just cut it because we need an active connection to the server at all times. This is where WebSockets come in. Think of it like a pipe that allows water (data) flow in and out from both sides.
Advantages of WebSockets over HTTPS
Websockets have a lot of advantages over traditional HTTPS, based on your project architecture it's normally faster in communication. Without the burden of doing response-request like in HTTP WebSockets offer real-time i-communication at its best with a bi-directional system of data transfer where there's no need to make requests to get responses.
Many services provide abstracted forms of WebSockets e.g. Firebase client communicates with its back-end over WebSockets, (of cause the protocols are undocumented). With this level of fast instant communication, developers can provide instant alerts, notifications, real-time messaging, and more services to users. Enough talk let’s jump in!!
Setting up Node Server
We would be working on two projects the server (nodeJS) and the client app (Flutter). The server is basically an echo server, it receives the data and sends it to everyone listening in. It’s the bridge between clients.
The client is just the flutter app that would be making use of the web socket to receive messages. Now we set up the server:
Create a new folder with the name of your project e.g socket_chat_server
Create a package.json file in that folder
Switch the current directory to your folder if you haven’t
Run npm init and complete your setup
Modify the package.json file to add the two dependencies we would need:
package.json
<a href="https://medium.com/media/bc0520fa6177b68f59385d183eb8ddac/href">https://medium.com/media/bc0520fa6177b68f59385d183eb8ddac/href</a>
Then we install the npm modules by running npm install .
index.js
The last step would be to create an echo server as follows:
<a href="https://medium.com/media/0561dcb2c1d58aebde666a4e89bea310/href">https://medium.com/media/0561dcb2c1d58aebde666a4e89bea310/href</a>
It's super simple, start a connection, then listen with client.on , next, pass in an event to listen to e.g “message” and emit (send) the data received right away back to everyone listening to the server. Your WebSocket should be running at http://localhost:3000 .
Test your server by running npm start. You should get :
Setting Up Flutter App
The flutter application would act as a client to receive and send messages to the server. Create a new project by running flutter create socket_chat.
There are a couple of different socket-io packages on pub.dev but I think socket_io_client is easier to use as its a replica of the js library :
⚠️ Note
When connecting to localhost on android emulators you might need a little more configuration, running adb reverse tcp:3000 tcp:3000 solved the issue allowed connections to the localhost via: http://127.0.0.1:3000 on android.
After deleting the code for the default counter app process to create a home.dart to implement our socket
main.dart
<a href="https://medium.com/media/374ba374f8479810d49e1409d5f8520f/href">https://medium.com/media/374ba374f8479810d49e1409d5f8520f/href</a>
The above is a very simple implementation of our WebSocket, and it has functions to listen to events and to send events to our server.
Deploying to CI/CD for Testing
During your development, you might want to use different WebSockets for different versions of your application (Quality Assurance, Development, or Production) environments, so it is very good practice to integrate host URLs and such very important code secrets into an encrypted CI/CD Build. Also using a CI/CD has become a norm for good testable and scalable mobile apps, and hence it's essential and encouraged to always favor having one for your flutter packages, flutter apps, and the likes.
There are lots of ways to integrate a CI/CD workflow in codemagic.io. I’ll like to go a more interesting but complex route and explain how to create a dev and a prod workflow via a plain old .yaml file and load unto your Codemagic.io project in no time. Yes I know there’s a GUI but sometimes you need to test a CI/CD flow without interrupting existing ones or creating a new flow with the GUI. So here’s a fast but easy way to do this:
Configurations and Environments
We would be creating our CI/CD & Environment structure ina way we can use both dynamic values from Codemagic and fixed environment values from our config.
The structure is straightforward, we have our raw JSON file config/appconfig.json, this will house our production and development host URLs. You would also need to define it as follows.
assets:
- config/app_config.jsonThe code at lib/config/config_loader.dart handles loading the data from our raw JSON file (config/appconfig.json) .
env.dart and env_config.dart handle creating our different environments to be used in _dev.dart & _prod.dart .
For most flutter applications main.dart is the entry file to the flutter applications. but for this, to work we would need to create main_common.dart , main_dev.dart and a main_prod.dart files, as the name implies main_common.dart will be the bridge to select the preferred environment. To run our code can no longer use flutter run but we would need to specify a new target entry depending on the config we wish to run.
We now have:
flutter run -t lib/main_dev.dart for Development
and
flutter run -t lib/main_prod.dart for Production.
<a href="https://medium.com/media/5d2c5e1ee1c1ed384853c6f78945d66d/href">https://medium.com/media/5d2c5e1ee1c1ed384853c6f78945d66d/href</a>
Environment Variable
Net we would have to convert our raw JSON config to base64 so we can add it as an environment variable to codemagic.yaml, you can find more info on this here.
Codemagic.yaml
Codemagic gives you the power to write out your workflow in an easily customizable yaml syntax.
We would create and modify our codemagic.yaml file as follows
<a href="https://medium.com/media/add396fde967d54fe8d3fd4fce0a4f07/href">https://medium.com/media/add396fde967d54fe8d3fd4fce0a4f07/href</a>
By defining our Environment variables as follows:
vars:APP_CONFIG: ewogICJkZXZIb3N0IjogIkRldmVsb3BtZW50IEhvc3QiLAogICJwcm9kSG9zdCI6ICJQcm9kdWN0aW9uIEhvc3QiCn0KBy inserting this piece of code above we can delete the /config/app_config.json and have it created when our CI Build is run.
# Write out the environment variable as a json file
echo $APP_CONFIG | base64 --decode > $FCI_BUILD_DIR/config/app_config.jsonNote: Our target entry filelib/main_dev.dart in our codemagic.yaml file should be changed to lib/main_prod.dart for a production workflow.
Running our Build
After committing our codemagic.yaml file and pushing to your preferred SCM (GitHub, bitbucket, etc.), click on “Start your first build”
Your workflow file should be detected automatically:
Click on “Start new build”
Voila, we have our build running.
The End
Websockets are fast, easy to set up, and can still be RESTful. they can be used for a wide range of projects. And we also see that it's super easy to set up workflows and integrate different environment variables/app secrets into Codemagic CI/CD the joy is you only have to do this once, after this setup you may choose to add more env configs or modify existing ones.
If you want to see the code for more advanced use of WebSockets and a Codemagic CI/CD flow config, you can check out the complete code at https://github.com/Zfinix/socket_chat/.
Thank you.












