stock-news-app / app / src / main / java / edu / utap / stocknewsapp / api / FinnHubApi.kt
FinnHubApi.kt
Raw
package edu.utap.stocknewsapp.api

import android.os.SystemClock
import android.text.SpannableString
import android.util.Log
import com.google.gson.GsonBuilder
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query
import java.lang.reflect.Type
import java.util.concurrent.TimeUnit

interface FinnHubApi {
    // Function prototypes with Retrofit annotations
    // @GET contains a string appended to the base URL
    // the string is called a path name
    @GET("/api/v1/quote?token=ce20qh2ad3idecbgmsa0ce20qh2ad3idecbgmsag")
    suspend fun getQuote(@Query("symbol") entity: String) : QuoteResponse

    // This class allows Retrofit to parse items in our model of type
    // SpannableString.  Note, given the amount of "work" we do to
    // enable this behavior, one can argue that Retrofit is a bit...."simple."
    class SpannableDeserializer : JsonDeserializer<SpannableString> {
        // @Throws(JsonParseException::class)
        override fun deserialize(
            json: JsonElement,
            typeOfT: Type,
            context: JsonDeserializationContext
        ): SpannableString {
            return SpannableString(json.asString)
        }
    }

    companion object {
        // Tell Gson to use our SpannableString deserializer
        private fun buildGsonConverterFactory(): GsonConverterFactory {
            val gsonBuilder = GsonBuilder().registerTypeAdapter(
                SpannableString::class.java, SpannableDeserializer()
            )
            return GsonConverterFactory.create(gsonBuilder.create())
        }
        // Keep the base URL simple
        private var httpurl = HttpUrl.Builder()
            .scheme("https")
            .host("finnhub.io")
            .build()
        fun create(): FinnHubApi = create(httpurl)
        private fun create(httpUrl: HttpUrl): FinnHubApi {
            val client = OkHttpClient.Builder()
                .connectTimeout(1, TimeUnit.MINUTES)
                .writeTimeout(1, TimeUnit.MINUTES) // write timeout
                .callTimeout(1, TimeUnit.MINUTES)
                .readTimeout(1, TimeUnit.MINUTES) // read timeout
                .retryOnConnectionFailure(true)
                .addInterceptor(HttpLoggingInterceptor().apply {
                    // Enable basic HTTP logging to help with debugging.
                    this.level = HttpLoggingInterceptor.Level.BASIC
                })
                .addInterceptor{ chain ->
                    val request = chain.request()
                    //var response = chain.proceed(request)
                    var response: Response? = null
                    var responseOK = false
                    var tryCount = 0
                    while (!responseOK && tryCount < 3) {
                        try {
                            SystemClock.sleep(3000)
                            response = chain.proceed(request)
                            responseOK = response.isSuccessful
                        } catch (e: Exception) {
                            Log.d("intercept", "Request is not successful - $tryCount")
                        } finally {
                            tryCount++
                        }
                    }
                    response!!
                }
                .build()
            return Retrofit.Builder()
                .baseUrl(httpUrl)
                .client(client)
                .addConverterFactory(buildGsonConverterFactory())
                .build()
                .create(FinnHubApi::class.java)
        }
    }
}