Networking setup

mvvm setup for onboard
live data implementation
This commit is contained in:
2024-05-06 20:59:43 +05:30
parent 55e654b073
commit 65c6f4fff1
17 changed files with 277 additions and 6 deletions

View File

@@ -15,7 +15,18 @@
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-05-02T15:28:18.084749Z" />
<timeTargetWasSelectedWithDropDown value="2024-05-03T09:15:20.379362Z" />
<targetsSelectedWithDialog>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$PROJECT_DIR$/../.android/avd/6.7_Horizontal_Fold-in_API_34.avd" />
</Key>
</deviceKey>
</Target>
</targetsSelectedWithDialog>
</State>
</entry>
</value>

View File

@@ -19,9 +19,19 @@ android {
buildTypes {
release {
buildConfigField "String", "WOKA_STAGINNG_BASE_URL", WOKA_STAGINNG_BASE_URL
buildConfigField "String", "WOKA_USER_NAME", WOKA_USER_NAME
buildConfigField "String", "WOKA_PASSWORD", WOKA_PASSWORD
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug{
buildConfigField "String", "WOKA_STAGINNG_BASE_URL", WOKA_STAGINNG_BASE_URL
buildConfigField "String", "WOKA_USER_NAME", WOKA_USER_NAME
buildConfigField "String", "WOKA_PASSWORD", WOKA_PASSWORD
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
@@ -33,6 +43,7 @@ android {
buildFeatures{
viewBinding true
buildConfig true
}
}
@@ -49,6 +60,17 @@ dependencies {
// dynamic sizes
implementation 'com.intuit.sdp:sdp-android:1.1.1'
// retrofit
def retrofit_version = "2.11.0"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
def lifecycle_version = "2.7.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
implementation libs.androidx.core.ktx
implementation libs.androidx.appcompat
implementation libs.material

View File

@@ -0,0 +1,10 @@
package com.woka.networking
/*
This is the basic structure of api response
*/
data class ApiResponse<T>(
val success: Int? = null,
val message: String? = null,
val data: T? = null
)

View File

@@ -0,0 +1,9 @@
package com.woka.networking
sealed class ApiResult<T>(data: T? = null, errorMessage: String? = null) {
class Loading<T>: ApiResult<T>()
class Success<T>(data: T? = null): ApiResult<T>(data)
class Error<T>(errorMessage: String? = null): ApiResult<T>(errorMessage = errorMessage)
}

View File

@@ -0,0 +1,53 @@
package com.woka.networking
import android.annotation.SuppressLint
import android.content.Context
import android.provider.Settings
import com.woka.BuildConfig
import com.woka.WokaApp.Companion.userPrefs
import okhttp3.Credentials
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitHelper {
private var retrofit: Retrofit? = null
@SuppressLint("HardwareIds")
private fun createRetrofit(): Retrofit{
val clientBuilder = OkHttpClient.Builder()
if (BuildConfig.DEBUG){
clientBuilder.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
})
}
// adding static headers for api calls
clientBuilder.addInterceptor(
Interceptor { chain ->
val request = chain.request().newBuilder()
request.addHeader("Accept-Language", if (userPrefs?.appLanguage == "hi") "Hindi" else "English")
request.addHeader("device-id", userPrefs?.deviceId!!)
request.addHeader("Authorization", Credentials.basic(BuildConfig.WOKA_USER_NAME, BuildConfig.WOKA_PASSWORD))
chain.proceed(request.build())
})
retrofit = Retrofit.Builder()
.baseUrl(BuildConfig.WOKA_STAGINNG_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(clientBuilder.build())
.build()
return retrofit!!
}
fun getRetrofit(): Retrofit{
return retrofit ?: createRetrofit()
}
}

View File

@@ -8,16 +8,15 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.app.ActivityOptionsCompat
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.navigation.fragment.findNavController
import com.woka.R
import com.woka.databinding.FragmentLanguageBinding
import com.woka.onboard.OnboardActivity
import com.woka.utils.ProgressView
import com.woka.utils.changeLocale
class LanguageFragment : Fragment() {
private lateinit var binding: FragmentLanguageBinding
private lateinit var progressView: ProgressView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -29,12 +28,12 @@ class LanguageFragment : Fragment() {
savedInstanceState: Bundle?
): View? {
binding = FragmentLanguageBinding.inflate(inflater, container, false)
progressView = ProgressView(requireContext(), "please wait...")
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
clickEvents()
}

View File

@@ -0,0 +1,4 @@
package com.woka.onboard.models
data class LoginResponse(
val result: Result
)

View File

@@ -0,0 +1,6 @@
package com.woka.onboard.models
data class Result(
val already_logged_in: Boolean,
val is_deactive: Boolean
)

View File

@@ -0,0 +1,14 @@
package com.woka.onboard.mvvm
import com.woka.networking.ApiResponse
import com.woka.onboard.models.LoginResponse
import okhttp3.FormBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
interface OnboardApiService {
@GET("login")
suspend fun login(@Body body: FormBody): Response<ApiResponse<LoginResponse>>
}

View File

@@ -0,0 +1,27 @@
package com.woka.onboard.mvvm
import com.woka.networking.ApiResult
import com.woka.onboard.models.LoginResponse
import okhttp3.FormBody
class OnboardRepository(private val apiService: OnboardApiService) {
suspend fun login(userName: String, password: String): ApiResult<LoginResponse> {
return try {
val response = apiService.login(
FormBody.Builder()
.add("username", userName)
.add("password", password)
.build()
)
if (response.body()?.success == 1)
ApiResult.Success(response.body()?.data)
else
ApiResult.Error(errorMessage = response.body()?.message)
} catch (e: Exception) {
ApiResult.Error(errorMessage = e.message)
}
}
}

View File

@@ -0,0 +1,28 @@
package com.woka.onboard.mvvm
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.woka.networking.ApiResult
import com.woka.networking.RetrofitHelper
import com.woka.onboard.models.LoginResponse
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class OnboardViewModel: ViewModel(){
private val repository: OnboardRepository = OnboardRepository(RetrofitHelper.getRetrofit().create(OnboardApiService::class.java))
private val _signInLiveData = MutableLiveData<ApiResult<LoginResponse>>()
val signInLiveData: LiveData<ApiResult<LoginResponse>>
get() = _signInLiveData
fun login(userName: String, password: String){
viewModelScope.launch {
_signInLiveData.postValue(ApiResult.Loading())
delay(6000)
_signInLiveData.postValue(ApiResult.Success())
}
}
}

View File

@@ -1,8 +1,11 @@
package com.woka.userPreference
import android.annotation.SuppressLint
import android.content.Context
import android.content.Context.MODE_PRIVATE
import android.content.SharedPreferences
import android.provider.Settings
import android.provider.Settings.Secure
class UserPreference(context: Context) {
@@ -12,6 +15,8 @@ class UserPreference(context: Context) {
}
private val userPrefs: SharedPreferences = context.getSharedPreferences(USER_PREFERENCE, MODE_PRIVATE)
@SuppressLint("HardwareIds")
val deviceId: String = Secure.getString(context.contentResolver, Secure.ANDROID_ID)
var appLanguage: String
get() = userPrefs.getString(APP_LANGUAGE, "en")?:"en"

View File

@@ -0,0 +1,33 @@
package com.woka.utils
import android.app.Dialog
import android.content.Context
import android.content.ContextWrapper
import android.view.LayoutInflater
import com.woka.databinding.LayoutProgressViewBinding
class ProgressView(context: Context, title: String): ContextWrapper(context) {
private val dialog: Dialog = Dialog(this)
private var binding: LayoutProgressViewBinding = LayoutProgressViewBinding.inflate(LayoutInflater.from(this))
init {
// init dialog
dialog.setContentView(binding.root)
dialog.setCancelable(false)
// transparent background
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
// init views
binding.title.text = title
}
fun show() = dialog.show()
fun hide() = dialog.dismiss()
fun setTitle(title: String) {
binding.title.text = title
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white"
/>
<corners android:radius="25dp"
/>
</shape>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:gravity="center"
android:paddingVertical="@dimen/_25sdp"
android:paddingHorizontal="@dimen/_30sdp"
android:background="@drawable/round_25"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:indeterminateTint="@color/color_primary"
/>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="@string/please_wait"
android:fontFamily="@font/exo_2_bold"
android:textColor="@color/color_primary"
android:textSize="16sp"
android:textAlignment="center"
android:layout_marginTop="15dp"
/>
</LinearLayout>

View File

@@ -68,4 +68,5 @@
<string name="reset_password">RESET PASSWORD</string>
<string name="back_btn" translatable="false">back_btn</string>
<string name="enter_your_password">Enter your password</string>
<string name="please_wait">Please wait...</string>
</resources>

View File

@@ -20,4 +20,10 @@ kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.nonTransitiveRClass=true
# BASE URLS
WOKA_STAGINNG_BASE_URL="https://wokaland.com/admin/api/"
WOKA_USER_NAME="admin"
WOKA_PASSWORD="Woka@1234"