A Retrofit inspired WebSocket client for Kotlin, Java, and Android

Related tags

Utility Scarlet
Overview

Scarlet

CircleCI

A Retrofit inspired WebSocket client for Kotlin, Java, and Android.

Update

We are working on a new version of Scarlet that supports other persistent connection protocols: ServerSentEvent, Socket IO, STOMP, and MQTT. It can be found on the 0.2.x branch.

Tutorial

Usage

In this example, we read the realtime Bitcoin price from Gdax WebSocket Feed. For more information, please check out the demo app.

Declare a WebSocket client using an interface:

interface GdaxService {
	@Receive
	fun observeWebSocketEvent(): Flowable<WebSocket.Event>
	@Send
	fun sendSubscribe(subscribe: Subscribe)
	@Receive
 	fun observeTicker(): Flowable<Ticker>
}

Use Scarlet to create an implementation:

val scarletInstance = Scarlet.Builder()
    .webSocketFactory(okHttpClient.newWebSocketFactory("wss://ws-feed.gdax.com"))
    .addMessageAdapterFactory(MoshiMessageAdapter.Factory())
    .addStreamAdapterFactory(RxJava2StreamAdapterFactory())
    .build()

val gdaxService = scarletInstance.create<GdaxService>()

Send a Subscribe message upon connection open and the server will start streaming tickers which contain the latest price.

val BITCOIN_TICKER_SUBSCRIBE_MESSAGE = Subscribe(
    productIds = listOf("BTC-USD"),
    channels = listOf("ticker")
)

gdaxService.observeWebSocketEvent()
    .filter { it is WebSocket.Event.OnConnectionOpened<*> }
    .subscribe({
        gdaxService.sendSubscribe(BITCOIN_TICKER_SUBSCRIBE_MESSAGE)
    })

gdaxService.observeTicker()
    .subscribe({ ticker ->
        Log.d("Bitcoin price is ${ticker.price} at ${ticker.time}")
    })

Android

Scarlet is driven by a StateMachine.

TODO

Download

Scarlet is available via Maven Central.

Snapshots of the development version are available in Sonatype's snapshots repository.

Maven:
<dependency>
    <groupId>com.tinder.scarlet</groupId>
    <artifactId>scarlet</artifactId>
    <version>0.1.12</version>
</dependency>
Gradle:
implementation 'com.tinder.scarlet:scarlet:0.1.12'

Plug-in Roadmap

WebSocket.Factory

  • OkHttpClient
  • MockHttpServer

MessageAdapter.Factory

  • moshi
  • gson
  • protobuf
  • jackson
  • simple-xml

StreamAdapter.Factory

  • RxJava2
  • RxJava1
  • Kotlin Coroutine

Lifecycle

  • AndroidLifecycle

BackoffStrategy

  • Linear
  • Exponential
  • ExponentialWithJitter

Copyright

Copyright (c) 2018, Match Group, LLC
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of Match Group, LLC nor the names of its contributors
      may be used to endorse or promote products derived from this software
      without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL MATCH GROUP, LLC BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Comments
  • 0.1.x: Lifecycle compilation error

    0.1.x: Lifecycle compilation error

    com.android.builder.multidex.D8MainDexList$MainDexListException: 
    com.android.tools.r8.errors.CompilationError: 
    Program type already present: com.tinder.scarlet.lifecycle.android.BuildConfig
    
    opened by ParfenovVS 17
  • ConnnectivityOnLifecycle does not close / re-open socket connection

    ConnnectivityOnLifecycle does not close / re-open socket connection

    When using Scarlet with OkHttp websocket + AndroidLifecycle with `ofApplicationForeground in the configs, putting the app in the background and bringing back forward closes & re-initiates the connection.

    However, turning on/off the airplane mode does not close & re-initiate the socket connection.

    opened by raylee4204 11
  • Scarlet in Java/Android

    Scarlet in Java/Android

    Hi, I'm having trouble integrating Scarlet into my Android app written in Java. Can you provide an example please (maybe put it in the Readme section along with the Kotlin example)?

    opened by subzero10 10
  • How do we use coroutine adapter? I can't find an example for the life of me.

    How do we use coroutine adapter? I can't find an example for the life of me.

    Can someone please give me an example on how to use kotlin coroutines with scarlet? Like how to set it up and how to "Observe" the data etc.. Thank you

    opened by Orpheus007 8
  • Connection reconnects constantly instead of sending ping

    Connection reconnects constantly instead of sending ping

    I've started using Scarlet this week and I've noticed that the WebSocket connection fails and a new one is started every minute or so. Is there an easy way to keep the connection open by sending a ping instead of re-connecting every time?

    I'm using version 0.1.7.

    opened by francos 8
  • Scarlet causing crash for no reason

    Scarlet causing crash for no reason

    Here is the stacktrace

    Caused by: java.lang.IllegalArgumentException: A method must have one and only one service method annotation: com.tinder.scarlet.internal.stub.StubMethod$Factory@f690cc7 at com.tinder.scarlet.internal.stub.StubMethod$Factory.create(StubMethod.kt:38) at com.tinder.scarlet.internal.stub.StubInterface$Factory.findStubMethods(StubInterface.kt:48) at com.tinder.scarlet.internal.stub.StubInterface$Factory.create(StubInterface.kt:42) at com.tinder.scarlet.Scarlet.create(Scarlet.kt:88) at com.careclues.channels.di.ChatModule.provideRocketChatWSApi(ChatModule.kt:118) at com.careclues.channels.di.ChatModule_ProvideRocketChatWSApiFactory.provideRocketChatWSApi(ChatModule_ProvideRocketChatWSApiFactory.java:35) at com.careclues.channels.DaggerCareCluesApplication_HiltComponents_ApplicationC.getRocketChatWSApi(DaggerCareCluesApplication_HiltComponents_ApplicationC.java:516) at com.careclues.channels.DaggerCareCluesApplication_HiltComponents_ApplicationC.getChatRepository(DaggerCareCluesApplication_HiltComponents_ApplicationC.java:615) at com.careclues.channels.DaggerCareCluesApplication_HiltComponents_ApplicationC.access$4600(DaggerCareCluesApplication_HiltComponents_ApplicationC.java:161) at com.careclues.channels.DaggerCareCluesApplication_HiltComponents_ApplicationC$SwitchingProvider.get(DaggerCareCluesApplication_HiltComponents_ApplicationC.java:1343) at com.careclues.channels.ui.login.LoginViewModel_AssistedFactory.create(LoginViewModel_AssistedFactory.java:33) at com.careclues.channels.ui.login.LoginViewModel_AssistedFactory.create(LoginViewModel_AssistedFactory.java:14) at androidx.hilt.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:76) at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:69) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185) at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150) at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:54) at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:41) at com.careclues.channels.ui.login.LoginActivity.getViewModel(Unknown Source:2) at com.careclues.channels.ui.login.LoginActivity.onCreate(LoginActivity.kt:47) at android.app.Activity.performCreate(Activity.java:7009) at android.app.Activity.performCreate(Activity.java:7000) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)  at android.app.ActivityThread.-wrap11(Unknown Source:0)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)  at android.os.Handler.dispatchMessage(Handler.java:106)  at android.os.Looper.loop(Looper.java:164)  at android.app.ActivityThread.main(ActivityThread.java:6494)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

    Here is the interface. As you can see, all the methods are annotated properly. Can anyone please tell me what is the issue?

    `interface RocketChatWSApi {

    @Send
    fun connect(connectMsg: ChatConnectMsg = ChatConnectMsg())
    
    @Send
    fun login(login: MethodCall<List<ChatLoginWSRequest>>)
    
    @Send
    fun loginWithToken(login: MethodCall<List<ChatTokenLoginWSRequest>>)
    
    @Send
    fun getRooms(getRoomsRequest: MethodCall<List<GetRoomsWSRequest>>)
    
    @Send
    fun markMessagesAsRead(markReadRequest: MethodCall<List<String>>)
    
    @Send
    fun subscribeToStream(request: SubscriptionCall)
    
    @Send
    fun sendMessage(sendMessageRequest: MethodCall<List<Any>>)
    
    @Send
    fun sendPong(pongMsg: PongMsg = PongMsg())
    
    @Receive
    fun receiveRocketChatMessages(): Flowable<RocketChatWSResponse>
    
    @Receive
    fun observeWebSocketEvent(): Flowable<WebSocketEvent>
    

    }`

    opened by tapandesai 6
  • java.lang.NullPointerException: subscribeActual failed

    java.lang.NullPointerException: subscribeActual failed

    Not sure if this a bug in scarlet, in RxJava or just unsupported use case. Repro steps unknown it is anonymous crash report.

    Scarlet usage related to cancelation looks like this:

    job = launch {
            fooService.receiveFoo().consumeEach { foo -> //...
      }
    }
    

    job may be canceled at anytime.

    Scarlet version: 0.1.4 Stacktrace:

    java.lang.NullPointerException: subscribeActual failed
           at io.reactivex.Maybe.empty(SourceFile:3732)
           at io.reactivex.internal.operators.maybe.MaybeMap.subscribeActual(SourceFile:40)
           at io.reactivex.Maybe.empty(SourceFile:3727)
           at io.reactivex.internal.operators.maybe.MaybeFilter.subscribeActual(SourceFile:39)
           at io.reactivex.Maybe.empty(SourceFile:3727)
           at io.reactivex.internal.operators.maybe.MaybeMap.subscribeActual(SourceFile:40)
           at io.reactivex.Maybe.empty(SourceFile:3727)
           at io.reactivex.internal.operators.maybe.MaybeFilter.subscribeActual(SourceFile:39)
           at io.reactivex.Maybe.empty(SourceFile:3727)
           at io.reactivex.internal.operators.maybe.MaybeMap.subscribeActual(SourceFile:40)
           at io.reactivex.Maybe.empty(SourceFile:3727)
           at io.reactivex.internal.operators.flowable.FlowableFlatMapMaybe$FlatMapMaybeSubscriber.getOrCreateQueue(SourceFile:132)
           at io.reactivex.internal.operators.flowable.FlowableObserveOn$ObserveOnSubscriber.runAsync(SourceFile:400)
           at io.reactivex.internal.operators.flowable.FlowableObserveOn$BaseObserveOnSubscriber.run(SourceFile:176)
           at io.reactivex.internal.schedulers.ScheduledRunnable.run(SourceFile:61)
           at io.reactivex.internal.schedulers.ScheduledRunnable.call(SourceFile:52)
           at java.util.concurrent.FutureTask.run(FutureTask.java:237)
           at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:154)
           at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
           at java.lang.Thread.run(Thread.java:818)
    
    Caused by kotlinx.coroutines.experimental.JobCancellationException: Child job was cancelled because of parent failure
    
    
    Caused by kotlinx.coroutines.experimental.JobCancellationException: Job was cancelled normally
    
    opened by koral-- 6
  • Method return type must not include a type variable or wildcard

    Method return type must not include a type variable or wildcard

    I'm getting the following error: IllegalArgumentException: Method return type must not include a type variable or wildcard: io.reactivex.Flowable<com.tinder.scarlet.WebSocket$Event$OnConnectionOpened<?>> at @Receive fun observeOnConnectionOpenedEvent(): Flowable<WebSocket.Event.OnConnectionOpened<*>>

    fun <T> create(service: Class<T>): T { val clientBuilder = OkHttpClient.Builder() clientBuilder.addInterceptor(AuthInterceptor() val scarlet = Scarlet.Builder() .webSocketFactory(clientBuilder.build().newWebSocketFactory(ApiEndPoint.WEBSOCKET)) .addMessageAdapterFactory(GsonMessageAdapter.Factory()) .addStreamAdapterFactory(RxJava2StreamAdapterFactory()) .build() return scarlet.create(service) }

    val websocketApi = BaseScarletBuilder.create(WebsocketApi::class.java)

    Is this the way we are suppose to use the lib?

    opened by kikebodi 6
  • scarlet-websocket-okhttp > 0.1.7 is not available from jitpack.io

    scarlet-websocket-okhttp > 0.1.7 is not available from jitpack.io

    Hello!

    I'm trying to add this dependency:

    Gradle Kotlin DSL

    implementation("com.github.tinder.scarlet:scarlet-websocket-okhttp:0.2.4")
    

    But all versions > 1.7.0 (I tried 1.8.0 ... 2.4.0) are not available.

    opened by petersamokhin 5
  • How to use dynamic path like Retrofit?

    How to use dynamic path like Retrofit?

    My case is open WSocket with domain: abcd.xyz/admin

    • 1 endpoint to handshake with server.
    • 1 endpoint to subcribe one event.

    So how to use dynamic path like Retrofit or must change base WS url? Many thanks!

    opened by hantrungkien 5
  • Couroutines Adapter Error

    Couroutines Adapter Error

    I am trying to consume my WebSocket service. I implemented it successfully using Rx, but when I am trying to migrate to coroutines, I am experiencing a crash.

    dependencies:

    implementation 'com.tinder.scarlet:scarlet:0.1.11'
    implementation 'com.tinder.scarlet:websocket-okhttp:0.1.11'
    implementation 'com.tinder.scarlet:message-adapter-gson:0.1.11'
    implementation 'com.tinder.scarlet:stream-adapter-coroutines:0.1.11'
    

    This code:

    Scarlet.Builder()
        .webSocketFactory(okHttpClient.newWebSocketFactory(wsBaseUrl))
        .addMessageAdapterFactory(GsonMessageAdapter.Factory())
        .addStreamAdapterFactory(CoroutinesStreamAdapterFactory())
        .build()
        .create<MyService>()
        .myReceiveFunction()
        .onEach {  /* something */ }
        .launchIn(applicationScope)
    

    will cause the application to crash with stacktrace. please don't mind the fact that the package name contains the word stomp, this needs to be changed as I am no longer using that protocol.

    Process: pl.rm.androidstomp, PID: 22946
        java.lang.RuntimeException: Unable to create application pl.rm.androidstomp.App: java.lang.NullPointerException: Attempt to invoke virtual method 'kotlinx.coroutines.internal.LockFreeLinkedListNode kotlinx.coroutines.internal.LockFreeLinkedListHead.getPrevNode()' on a null object reference
            at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6612)
            at android.app.ActivityThread.access$1300(ActivityThread.java:233)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1896)
            at android.os.Handler.dispatchMessage(Handler.java:106)
            at android.os.Looper.loop(Looper.java:223)
            at android.app.ActivityThread.main(ActivityThread.java:7523)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
         Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'kotlinx.coroutines.internal.LockFreeLinkedListNode kotlinx.coroutines.internal.LockFreeLinkedListHead.getPrevNode()' on a null object reference
            at kotlinx.coroutines.channels.AbstractSendChannel.getClosedForSend(AbstractChannel.kt:83)
            at kotlinx.coroutines.channels.AbstractSendChannel.isClosedForSend(AbstractChannel.kt:129)
            at kotlinx.coroutines.reactive.SubscriptionChannel.onSubscribe(Channel.kt:85)
            at io.reactivex.internal.subscribers.StrictSubscriber.onSubscribe(StrictSubscriber.java:85)
            at io.reactivex.internal.operators.flowable.FlowableFlatMapMaybe$FlatMapMaybeSubscriber.onSubscribe(FlowableFlatMapMaybe.java:103)
            at io.reactivex.internal.operators.flowable.FlowableObserveOn$ObserveOnSubscriber.onSubscribe(FlowableObserveOn.java:281)
            at io.reactivex.internal.operators.flowable.FlowableOnBackpressureBuffer$BackpressureBufferSubscriber.onSubscribe(FlowableOnBackpressureBuffer.java:90)
            at io.reactivex.processors.PublishProcessor.subscribeActual(PublishProcessor.java:148)
            at io.reactivex.Flowable.subscribe(Flowable.java:14419)
            at io.reactivex.internal.operators.flowable.FlowableOnBackpressureBuffer.subscribeActual(FlowableOnBackpressureBuffer.java:46)
            at io.reactivex.Flowable.subscribe(Flowable.java:14419)
            at io.reactivex.Flowable.subscribe(Flowable.java:14365)
            at io.reactivex.internal.operators.flowable.FlowableDefer.subscribeActual(FlowableDefer.java:41)
            at io.reactivex.Flowable.subscribe(Flowable.java:14419)
            at io.reactivex.internal.operators.flowable.FlowableObserveOn.subscribeActual(FlowableObserveOn.java:56)
            at io.reactivex.Flowable.subscribe(Flowable.java:14419)
            at io.reactivex.internal.operators.flowable.FlowableFlatMapMaybe.subscribeActual(FlowableFlatMapMaybe.java:54)
            at io.reactivex.Flowable.subscribe(Flowable.java:14419)
            at io.reactivex.Flowable.subscribe(Flowable.java:14368)
            at com.tinder.scarlet.utils.FlowableStream.subscribe(Unknown Source:2)
            at kotlinx.coroutines.reactive.ChannelKt.openSubscription(Channel.kt:25)
            at kotlinx.coroutines.reactive.ChannelKt.openSubscription$default(Channel.kt:23)
            at com.tinder.streamadapter.coroutines.ReceiveChannelStreamAdapter.adapt(ReceiveChannelStreamAdapter.kt:14)
            at com.tinder.streamadapter.coroutines.ReceiveChannelStreamAdapter.adapt(ReceiveChannelStreamAdapter.kt:12)
            at com.tinder.scarlet.internal.servicemethod.ServiceMethod$Receive.execute(ServiceMethod.kt:63)
            at com.tinder.scarlet.internal.servicemethod.ServiceMethodExecutor.execute(ServiceMethodExecutor.kt:21)
            at com.tinder.scarlet.internal.Service.execute(Service.kt:18)
            at com.tinder.scarlet.Scarlet$createInvocationHandler$1.invoke(Scarlet.kt:124)
            at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
            at $Proxy3.deviceChanges(Unknown Source)
            at pl.rm.api.networking.internal.websocket.scarlet.ScarletWebSocketService.deviceResponseUpdates(ScarletWebSocketService.kt:35)
            at pl.rm.api.networking.exposed.Networking.observeDevices(Networking.kt:16)
    2020-12-28 11:39:32.301 22946-22946/pl.rm.androidstomp E/AndroidRuntime:     at pl.rm.androidstomp.state.device.DeviceSynchronizer.liveUpdates(DeviceSynchronizer.kt:27)
            at pl.rm.androidstomp.state.device.DeviceSynchronizer.start(DeviceSynchronizer.kt:37)
            at pl.rm.androidstomp.App.onCreate(App.kt:16)
            at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1192)
            at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6607)
            	... 8 more
    
    

    Any idea what I am doing wrong? There is no official documentation as far as I know.

    opened by RafalManka 4
  • Duplicate class com.tinder.StateMachine found in modules statemachine-0.1.2 (com.github.tinder:statemachine:0.1.2) and statemachine-0.2.0 (com.tinder.statemachine:statemachine:0.2.0)

    Duplicate class com.tinder.StateMachine found in modules statemachine-0.1.2 (com.github.tinder:statemachine:0.1.2) and statemachine-0.2.0 (com.tinder.statemachine:statemachine:0.2.0)

    Duplicate class com.tinder.StateMachine found in modules statemachine-0.1.2 (com.github.tinder:statemachine:0.1.2) and statemachine-0.2.0 (com.tinder.statemachine:statemachine:0.2.0)

    opened by jamshidisoqov 2
  • Duplicate response from websocket is coming after a channel is unsubscribed and subscribed again

    Duplicate response from websocket is coming after a channel is unsubscribed and subscribed again

    I have a use case where I unsubscribe a channel and then subscribe again. But somehow multiple duplicate response is received . Below are my subscribe & unsubscribe methods `

    fun subscribeChannel() {
         viewModelScope.launchWithException {
                if (socketRepository.isSocketConnected) {
                    socketRepository.subscribeChannel(coinName, ChannelNameConstants.CHANNEL_ORDER_BOOK)
                } else {
                    val socketFlow = socketRepository.getWebSocketEvents()
                    socketFlow.collect {
                        when (it) {
                            is WebSocket.Event.OnConnectionOpened<*> -> {
                                socketRepository.isSocketConnected = true
                                socketRepository.subscribeChannel(coinName, ChannelNameConstants.CHANNEL_ORDER_BOOK)
                            }
                            is WebSocket.Event.OnConnectionClosed,
                            is WebSocket.Event.OnConnectionFailed -> {
                                socketRepository.isSocketConnected = false
                            }
                        }
                    }
                }
            }
    }
    
        fun unsubscribeChannel(coinName: String, channelName: String) {
        socketService.sendUnsubscribe(
            ChannelData(
                channelName = "$channelName ${SubscriptionType.UNSUBSCRIBE.value}",
                data = coinName
            )
        )
    }
    `
    
    opened by rohitiiita007 0
  • Malformed JSON when uses Gson

    Malformed JSON when uses Gson

    I am using GsonMessageAdapter.Factory() but i get {"type":"error","message":"Malformed JSON"} response. Can anyone tell how to use model class with scarlet? or if any example is there to use gson in scarlet

    opened by vishalbhanderii 1
  • My app receives several responses at the same time but only displays the last one

    My app receives several responses at the same time but only displays the last one

    When my app (Android) that implemented this lib in the websocket receives several responses at the same time from the backend, the last response overwrites the others and the app only displays the last one.

    opened by pontoevirgula 1
Releases(v0.1.12)
Owner
Tinder
Tinder Open Source Software
Tinder
General purpose utilities and hash functions for Android and Java (aka java-common)

Essentials Essentials are a collection of general-purpose classes we found useful in many occasions. Beats standard Java API performance, e.g. LongHas

Markus Junginger 1.4k Dec 29, 2022
General purpose utilities and hash functions for Android and Java (aka java-common)

Essentials Essentials are a collection of general-purpose classes we found useful in many occasions. Beats standard Java API performance, e.g. LongHas

Markus Junginger 1.4k Dec 29, 2022
Sticker-board for android inspired by uSticker (forked from woosticker)

Android.EweSticker Sticker-board for android inspired by uSticker (forked from woosticker). Features Screenshots How to use Lint with Language Informa

Kieran W 29 Dec 23, 2022
Multi-module, Kotlin, MVI, Compose, Hilt, Navigation Component, Use-cases, Room, Retrofit

Work in progress Multi-module demo app that gets data from dota2 api. API https://docs.opendota.com/ Players by rank (GET) https://api.opendota.com/ap

Mitch Tabian 321 Dec 27, 2022
Dagger Hilt, MVP Moxy, Retrofit, Kotlin coroutine, Sealed class

Dagger Hilt, MVP Moxy, Retrofit, Kotlin coroutine, Sealed class

Dostonjon 1 Nov 2, 2021
A cup of library to Parse RSS for android. Also available as a ConverterFactory for Retrofit & Fuel

ParseRSS RSS Parser for android Simple, concise, and extensible RSS Parser in the entire coffee shop. It can capture these information from the RSS ar

Muhammad Rifqi Fatchurrahman 23 Dec 10, 2022
gRPC and protocol buffers for Android, Kotlin, and Java.

Wire “A man got to have a code!” - Omar Little See the project website for documentation and APIs. As our teams and programs grow, the variety and vol

Square 3.9k Dec 31, 2022
Multiplaform kotlin library for calculating text differences. Based on java-diff-utils, supports JVM, JS and native targets.

kotlin-multiplatform-diff This is a port of java-diff-utils to kotlin with multiplatform support. All credit for the implementation goes to original a

Peter Trifanov 51 Jan 3, 2023
Bar Service Kotlin Client

A simple starter service client written in Kotlin against generated models (protos)A simple starter service client written in Kotlin against generated models (protos)

Logesh Dinakaran 0 Nov 9, 2021
DEMOMovieDB - Client App using movieDB with Kotlin

DEMOMovieDB DEMOMovieDB is a gorgeous client application for TMDb on Android, bu

null 0 Feb 15, 2022
Trail is a simple logging system for Java and Android. Create logs using the same API and the library will detect automatically in which platform the code is running.

Trail Trail is a simple logging system for Java and Android. Create logs using the same API and the library will detect automatically in which platfor

Mauricio Togneri 13 Aug 29, 2022
a simple cache for android and java

ASimpleCache ASimpleCache 是一个为android制定的 轻量级的 开源缓存框架。轻量到只有一个java文件(由十几个类精简而来)。 1、它可以缓存什么东西? 普通的字符串、JsonObject、JsonArray、Bitmap、Drawable、序列化的java对象,和 b

Michael Yang 3.7k Dec 14, 2022
A lightning fast, transactional, file-based FIFO for Android and Java.

Tape by Square, Inc. Tape is a collection of queue-related classes for Android and Java. QueueFile is a lightning-fast, transactional, file-based FIFO

Square 2.4k Dec 30, 2022
UPnP/DLNA library for Java and Android

Cling EOL: This project is no longer actively maintained, code may be outdated. If you are interested in maintaining and developing this project, comm

4th Line 1.6k Jan 4, 2023
Error handling library for Android and Java

ErrorHandler Error handling library for Android and Java Encapsulate error handling logic into objects that adhere to configurable defaults. Then pass

null 237 Dec 29, 2022
BinGait is a tool to disassemble and view java class files, developed by BinClub.

BinGait Tool to diassemble java class files created by x4e. Usage To run BinGait, run java -jar target/bingait-shadow.jar and BinGait will launch. If

null 18 Jul 7, 2022
Android tiny device flow client

OAuth 2.0 Device Flow Example Setup Create an Auth0 application Enable Device Code Grants in Advanced settings Disable Client Credentials Enable Devic

Kenji Saito 0 May 15, 2022
POC Simulate Backend Biometric Authentication with AIDL (client app/server app)

poc-simulate-bio-auth-aidl POC Simulate Backend Biometric Authentication with AIDL (client app/server app) #How to use Install server app and run Inst

gundamD 0 Dec 30, 2021
Java implementation of a Disk-based LRU cache which specifically targets Android compatibility.

Disk LRU Cache A cache that uses a bounded amount of space on a filesystem. Each cache entry has a string key and a fixed number of values. Each key m

Jake Wharton 5.7k Dec 31, 2022