Untitled

mail@pastecode.io avatar
unknown
plain_text
a month ago
8.0 kB
5
Indexable
Never


import android.os.Bundle
import android.util.Log
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import uk.co.parentapps.connect.BuildConfig
import uk.co.parentapps.connect.databinding.ActivitySchoolBinding
import uk.co.parentapps.connect.util.Constant
import uk.co.parentapps.connect.util.Constant.Companion.SCH_BASE_UK_DEBUG
import uk.co.parentapps.connect.util.Constant.Companion.SCH_BASE_UK_PROD
import uk.co.parentapps.connect.util.Constant.Companion.SCH_BASE_USA_DEBUG
import uk.co.parentapps.connect.util.Constant.Companion.SCH_BASE_USA_PROD
import uk.co.parentapps.connect.util.NetworkListener

@AndroidEntryPoint
class SchoolActivity: AppCompatActivity() {

    private lateinit var schoolBinding: ActivitySchoolBinding
    private lateinit var networkListener: NetworkListener
    private val schoolViewModel: SchoolViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        schoolBinding = ActivitySchoolBinding.inflate(layoutInflater)
        setContentView(schoolBinding.root)

        schoolViewModel.readBackOnline.observe(this) {
            schoolViewModel.backOnline = it
        }

        lifecycleScope.launch(Dispatchers.IO) {
            schoolViewModel.countryCodeFlow.collect{countryCode ->
                val baseUrl = when (countryCode) {
                    "uk" -> if (BuildConfig.BUILD_TYPE == "debug") SCH_BASE_UK_DEBUG else SCH_BASE_UK_PROD
                    "usa" -> if (BuildConfig.BUILD_TYPE == "debug") SCH_BASE_USA_DEBUG else SCH_BASE_USA_PROD
                    else -> SCH_BASE_UK_DEBUG
                }.toString()
                schoolViewModel.updateBaseURL(baseUrl)

                println("The Base URL ${schoolViewModel.getBaseURL()}")
            }
        }

        lifecycleScope.launch {
            lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED){
                networkListener = NetworkListener()
                networkListener.checkNetworkAvailability(this@SchoolActivity).collect{ status ->
                    Log.d("Network Listener : ", "Listener --- $status")
                    schoolViewModel.networkStatus = status
                    schoolViewModel.showNetworkStatus()
                    requestSchoolApi()
                }
            }
        }
    }

    private fun requestSchoolApi() {
        lifecycleScope.launch {
            requestApiData()
        }
    }

    private fun requestApiData() {
        Log.d("School Activity ", "Get School API call")
        schoolViewModel.getSchool()
        schoolViewModel.schoolDetailResponse.observe(this){ response ->
            println("Response $response")
        }
    }

}



// ViewModel

import android.app.Application
import android.widget.Toast
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import retrofit2.Response
import uk.co.parentapps.connect.data.SchoolRepository
import uk.co.parentapps.connect.data.SchoolStoreRepository
import uk.co.parentapps.connect.model.School
import uk.co.parentapps.connect.util.ApiConfig
import uk.co.parentapps.connect.util.NetworkResult
import javax.inject.Inject

@HiltViewModel
class SchoolViewModel @Inject constructor(
    private val schoolStoreRepository: SchoolStoreRepository,
    private val schoolRepository: SchoolRepository,
    private val apiConfig: ApiConfig,
    application: Application): AndroidViewModel(application) {

    var networkStatus = false
    var backOnline = false

    val readBackOnline = schoolStoreRepository.readBackOnline.asLiveData()

    val countryCodeFlow: Flow<String> = schoolStoreRepository.readCountryCode.map { it as String }

    var schoolDetailResponse: MutableLiveData<NetworkResult<School>?> = MutableLiveData()

    fun updateBaseURL(appUrl: String){
        apiConfig.setAppBaseUrl(appUrl)
    }

    fun getBaseURL(): String {
        return apiConfig.baseUrl
    }

    fun getSchool() = viewModelScope.launch {
        getSafeSchoolCall()
    }

    private suspend fun getSafeSchoolCall() {
        if (backOnline){
            try{
                val schoolResponse = schoolRepository.remoteStore.getSchools()
                schoolDetailResponse.value = handleSchoolResponse(schoolResponse)
            }catch (e: Exception){
                schoolDetailResponse.value = NetworkResult.Error("No School Found")
            }
        }else{
            schoolDetailResponse.value = NetworkResult.Error("No Internet Connection")
        }
    }

    private fun handleSchoolResponse(response: Response<School>): NetworkResult<School>? {
        when{
            response.message().toString().contains("timeout") -> {
                return NetworkResult.Error("Timeout")
            }
            response.code() == 500 -> {
                return NetworkResult.Error("Internal Server Error")
            }
            response.body()!!.schoolData.isEmpty() -> {
                return NetworkResult.Error("School Not Found")
            }
            response.isSuccessful -> {
                val schoolResult = response.body()
                return NetworkResult.Success(schoolResult!!)
            }
            else -> {
                return NetworkResult.Error(response.message())
            }
        }
    }

    private fun saveBackOnline(backOnline: Boolean) = viewModelScope.launch(Dispatchers.IO) {
        schoolStoreRepository.saveBackOnline(backOnline)
    }

    fun showNetworkStatus() {
        if (!networkStatus) {
            Toast.makeText(getApplication(), "No Internet Connection.", Toast.LENGTH_LONG).show()
            saveBackOnline(true)
        } else {
            if (backOnline) {
                Toast.makeText(getApplication(), "We're back online.", Toast.LENGTH_LONG).show()
                saveBackOnline(false)
            }
        }
    }
}

//Base URL

class ApiConfig {
    var baseUrl: String = ""

    fun setAppBaseUrl(url: String) {
        baseUrl = url
    }
}


//Network Module

import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import uk.co.parentapps.connect.data.api.SchoolApi
import uk.co.parentapps.connect.util.ApiConfig
import java.util.concurrent.TimeUnit
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
class NetworkModule {

    @Singleton
    @Provides
    fun provideHttpClient(): OkHttpClient {
        return OkHttpClient.Builder()
            .readTimeout(30, TimeUnit.SECONDS)
            .connectTimeout(30, TimeUnit.SECONDS)
            .build()
    }

    @Singleton
    @Provides
    fun provideConverterFactory(): GsonConverterFactory {
        return GsonConverterFactory.create()
    }

    @Singleton
    @Provides
    fun provideApiConfig(): ApiConfig {
        return ApiConfig() // Provide the ApiConfig instance
    }

    @Singleton
    @Provides
    fun providesRetrofitInstance(
        okHttpClient: OkHttpClient,
        gsonConverterFactory: GsonConverterFactory,
        apiConfig: ApiConfig
    ): Retrofit {
        return Retrofit.Builder()
            .baseUrl(apiConfig.baseUrl)
            .client(okHttpClient)
            .addConverterFactory(gsonConverterFactory)
            .build()
    }

    @Singleton
    @Provides
    fun provideApiService(retrofit: Retrofit): SchoolApi {
        return retrofit.create(SchoolApi::class.java)
    }
}
Leave a Comment