In mobile applications, the data layer is the real source of content displayed on the screen. However, when we integrated the WebSocket API into Tinder earlier this year, maintaining it became a headache. In order to integrate WebSocket more easily on Android, Scarlet t came into being, which is a declarative Kotlin library.
WebSocket is one of the options to implement the data layer in Android applications, especially when the application needs to update data in real time, such as chat, online multiplayer games and real-time feeds. It establishes a two-way connection between the client and the server. When the connection is open, they can send text and binary messages back and forth with low overhead. This article will teach you how to quickly implement WebSocket in Android applications.
set up
To implement Scarlet, first add it to app / build Gradle file.
dependencies { ... // scarlet implementation 'com.tinder.scarlet:scarlet:0.1.12' }
In the example provided by Scarlet, RxJava is used to help manage the data flow sent by the Web socket. In APP / build Implement it in gradle.
dependencies { // rx implementation 'io.reactivex.rxjava2:rxjava:2.2.21' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0' }
If you are curious about the support of Coroutine and Kotlin Flow, please see here: HTTPS: / / GitHub com/Tinder/Scarlet/issues/114
Now the important part of our setup is the service. We can use WebSocket echo( wss://WebSocket-echo.glitch.me )Test our WebSocket;
Create interface function
Next, create an interface to define the functions that communicate with WebSocket.
interface EchoService { @Receive fun observeConnection(): Flowable<WebSocket.Event> @Send fun sendMessage(param: String) }
As shown above, the service interface looks very similar to the transformation. You can use the @ Receive annotation to observe the data flow from the WebSocket and use @ Send to Send or subscribe data to the WebSocket.
After setting up the service, we can continue to implement the service in our activities; In this case, I did not use any architecture, but implemented the service in the Activity.
class MainActivity : AppCompatActivity() { ... private fun setupWebSocketService() { webSocketService = provideWebSocketService( scarlet = provideScarlet( client = provideOkhttp(), lifecycle = provideLifeCycle(), streamAdapterFactory = provideStreamAdapterFactory(), ) ) } private fun provideWebSocketService(scarlet: Scarlet) = scarlet.create(EchoService::class.java) private fun provideScarlet( client: OkHttpClient, lifecycle: Lifecycle, streamAdapterFactory: StreamAdapter.Factory, ) = Scarlet.Builder() .webSocketFactory(client.newWebSocketFactory(ECHO_URL)) .lifecycle(lifecycle) .addStreamAdapterFactory(streamAdapterFactory) .build() private fun provideOkhttp() = OkHttpClient.Builder() .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC)) .build() private fun provideLifeCycle() = AndroidLifecycle.ofApplicationForeground(application) private fun provideStreamAdapterFactory() = RxJava2StreamAdapterFactory() ... }
test
Now we can test the code by sending something to WebSocket. WebSocket will send the same message when they are retrieved.
class MainActivity : AppCompatActivity() { ... private fun sendMessage(message: String) { webSocketService.sendMessage(message) adapter.addItem(Message(message = message, isFromSender = true)) } @SuppressLint("CheckResult") private fun observeConnection() { webSocketService.observeConnection() .observeOn(AndroidSchedulers.mainThread()) .subscribe({ response -> Log.d("observeConnection", response.toString()) onReceiveResponseConnection(response) }, { error -> Log.e("observeConnection", error.message.orEmpty()) Snackbar.make(binding.root, error.message.orEmpty(), Snackbar.LENGTH_SHORT).show() }) } private fun onReceiveResponseConnection(response: WebSocket.Event) { when (response) { is OnConnectionOpened<*> -> changeToolbarTitle("connection opened") is OnConnectionClosed -> changeToolbarTitle("connection closed") is OnConnectionClosing -> changeToolbarTitle("closing connection..") is OnConnectionFailed -> changeToolbarTitle("connection failed") is OnMessageReceived -> handleOnMessageReceived(response.message) } } private fun handleOnMessageReceived(message: MessageScarlet) { adapter.addItem(Message(message.toValue(), false)) binding.etMessage.setText("") } private fun MessageScarlet.toValue(): String { return when (this) { is Text -> value is Bytes -> value.toString() } } ... }
summary
This is the whole content of this paper. Scarlett is a great library that allows you to access WebSocket in Android applications. You can easily set up Scarlett for your application through the above tutorial, especially if you are familiar with Retrofit and other tools.