Android Tutorial Part 1 Using Java-WebSocket With Kotlin

Fahri Can
The Startup
Published in
5 min readSep 20, 2020

In this tutorial, I will show how to use Java-Websocket Library together with Kotlin. It will be a simple app. The app opens a connection to the Coinbase Pro Websocket Feed by using Java-Websocket. When the connection is open the app will get the realtime Bitcoin price in Euro from Coinbase Pro. This is a step by step tutorial.

Prerequisites

You should already be familiar with Kotlin and Android development. I am using Android Studio 4.0.1. You should also know that a connection to a web socket is bidirectional. Once the connection is open the communication can happen to both sides from server to client or client to server. In case you are more interested in the differences between HTTP and web sockets, I recommend watching this YouTube video.

Why this article?

I recently had a coding challenge for a company where I had to use web sockets to get realtime stock prices. Because of the outdated resources and hard to use libraries. I thought there is a simple tutorial needed so every Android developer can easily use web sockets in 2020.

What the app will look like

The app will only contain a TextView on the main screen which shows the current Bitcoin price on Coinbase Pro in Euro.

finished app in portrait mode
finished app in landscape mode

Start new project

Go to Android Studio and create a new Empty Project (Language Kotlin, API 23).

Gradle dependencies

Go to your build.gradle(Project: WebSocketTutorial) file. Add mavenCentral() dependency in repositories {} so we can use Moshi later. Your allprojects{} dependency schould look like this:

allprojects dependencies

Go to your build.gradle(Module: app) file. Use the annotation processor for Kotlin

apply plugin: 'kotlin-kapt'

Now go to dependencies {} and copy/paste the dependency for Java-WebSocket and Moshi:

// WebSocket
implementation "org.java-websocket:Java-WebSocket:1.5.1"
// Moshi
implementation 'com.squareup.moshi:moshi:1.9.2'
kapt 'com.squareup.moshi:moshi-kotlin-codegen:1.9.2'

Coinbase Pro Websocket Feed

Let’s take a look at the websocket feed at https://docs.pro.coinbase.com/#websocket-feed

The websocket feed provides real-time market data updates for orders and trades.

websocket feed:wss://ws-feed.pro.coinbase.com

Okay, now to test if this websocket works, please open this URL: https://www.websocket.org/echo.html

  1. Copy-paste the web socket feed from Coinbase Pro after Location:
  2. from Coinbase Pro after Location:

2. Click on Connect

3. Look at Log: there must be written CONNECTED

4. Copy-paste following JSON below Message:

5. Finally click on Send

6. Then you should see RECEIVED: JSON objects

As you can see the websocket response looks like this:

websocket response

From the response we only need one field and this is the “price”.

Create the model

Create a data class called BitcoinTicker.kt with one field price, should be an optional String. Annotated the class with@JsonClass(generateAdapter = true) which will generate a JsonAdapter to handle serializing/deserializing to and from JSON of the specified type.

BitcoinTicker.kt

Create the layout to display the price

Open your activity_main.xml and replace the TextView below wit your current.

<TextView
android:id="@+id/btc_price_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

Let’s start implementing

The complete implementation will take place in MainActivity.kt and we will not need any other class. Go and open MainActivity.kt and create a lateinit var fo type WebSocketClient.

private lateinit var webSocketClient: WebSocketClient

Now override the onResume() method because at this lifecycle method the user can interact with the screen. Here create the method initWebSocket() in this method the logic will be implemented.

override fun onResume() {
super.onResume()
initWebSocket()
}

Before we implement the logic for getting data from the websocket, I would suggest we think first, when to close the websocket connection. In onResume() we start the connection. That’s why we should close the connection in onPause(). I would suggest every time you clear data or close a connection, you do it in the opposite lifecycle method. For onCreate() in onDestroy(), for onStart() in onStop(), for onResume() in onPause().

override fun onPause() {
super.onPause()
webSocketClient.close()
}

Okay, now we can start to implement initWebSocket(). The first thing we need is an URI object to pass it to our WebSocketClient. Create the following line:

val coinbaseUri: URI? = URI(WEB_SOCKET_URL)

The constant WEB_SOCKET_URL is not created yet. That’s why we need to create it in companion object {}.

companion object {
const val WEB_SOCKET_URL = "wss://ws-feed.pro.coinbase.com"
}

Back to the method initWebSocket() and create after the local variable coinbaseUri the method createWebSocketClient(coinbaseUri).

private fun initWebSocket() {
val coinbaseUri: URI? = URI(WEB_SOCKET_URL)

createWebSocketClient(coinbaseUri)
}

The method will contain an anonymous class of WebSocketClient with the implemented logic for onOpen(), onMessage(), onClose(), onError() and it will be assigned to our field webSocketClient.

private fun createWebSocketClient(coinbaseUri: URI?) {
webSocketClient = object : WebSocketClient(coinbaseUri) {

}
}

Start with onOpen()

Now you will see that object is underlined red. After you press ALT+Enter you will see a red light bulb with the text “implement members”. Just press okay for all of the methods. Let’s start with the first method onOpen(). As the name explains, this method is necessary to open the websocket connection. First, add a log statement so we can later see if everything works properly.

override fun onOpen(handshakedata: ServerHandshake?) {
Log.d(TAG, "onOpen")
}

The constant TAG is not created yet, so go back to companion object {} and create the constant there.

companion object {
const val WEB_SOCKET_URL = "wss://ws-feed.pro.coinbase.com"
const val TAG = "Coinbase"
}

Navigate back to the method onOpen() and add in the next line the method subscribe().

override fun onOpen(handshakedata: ServerHandshake?) {
Log.d(TAG, "onOpen")
subscribe()
}

Create the subscribe() method outside of createWebSocketClient(coinbaseUri: URI?). The subscribe() method will contain the following information:

To begin receiving feed messages, you must first send a subscribe message to the server indicating which channels and products to receive. This message is mandatory — you will be disconnected if no subscribe has been received within 5 seconds.

The subscribe message is the same we used in the section: Coinbase Pro Websocket Feed at point number 4. It will be that one:

This is how the method should look like:

Okay, that’s it for the first part, here is the second part

Here is the completed project, check out the branch part1:

--

--

Fahri Can
The Startup

Android Dev | Blogger | AI & Crypto Enthusiast