Skip to content

Commit

Permalink
Merge branch #26 into feat/#10-홈-화면-구현
Browse files Browse the repository at this point in the history
  • Loading branch information
bamin0422 committed Jan 1, 2024
2 parents b064b14 + f854667 commit f5b4fbf
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 7 deletions.
3 changes: 3 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,12 @@ dependencies {

implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.serialization.json)

implementation(libs.okhttp.logging)
implementation(libs.retrofit)
implementation(libs.retrofit.kotlin.serialization)
implementation(libs.retrofit.converter.gson)
implementation(libs.retrofit.converter.scalars)

implementation(libs.coroutines.core)
implementation(libs.fragment.ktx)
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/com/owori/android/core/AppConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.owori.android.core


object AppConfig {
const val TAG_DEBUG = "TAG_DEBUG"

}
36 changes: 33 additions & 3 deletions app/src/main/java/com/owori/android/core/OworiApplication.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,44 @@
package com.owori.android.core

import android.annotation.SuppressLint
import android.app.Application
import com.kakao.sdk.common.KakaoSdk
import android.content.Context
import androidx.annotation.StringRes
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.owori.android.R
import com.owori.android.module.NetworkConnectionChecker
import com.kakao.sdk.common.KakaoSdk
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class OworiApplication: Application() {
class OworiApplication : Application(), DefaultLifecycleObserver {
override fun onCreate() {
super.onCreate()
super<Application>.onCreate()
context = applicationContext
networkConnectionChecker = NetworkConnectionChecker(context)
KakaoSdk.init(this, getString(R.string.kakao_login_key))
}

override fun onStop(owner: LifecycleOwner) {
networkConnectionChecker.unregister()
super.onStop(owner)
}

override fun onStart(owner: LifecycleOwner) {
networkConnectionChecker.register()
super.onStart(owner)
}

companion object {
@SuppressLint("StaticFieldLeak")
private lateinit var context: Context

fun getString(@StringRes stringResId: Int): String {
return context.getString(stringResId)
}

private lateinit var networkConnectionChecker: NetworkConnectionChecker
fun isOnline() = networkConnectionChecker.isOnline()
}
}
56 changes: 56 additions & 0 deletions app/src/main/java/com/owori/android/core/di/NetworkModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.owori.android.core.di

import com.owori.android.R
import com.owori.android.core.OworiApplication
import com.owori.android.data.api.auth.AuthApi
import com.owori.android.module.HttpRequestInterceptor
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 retrofit2.converter.scalars.ScalarsConverterFactory
import javax.inject.Singleton

/*
* Created by JJJoonngg
*/

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
const val NETWORK_EXCEPTION_OFFLINE_CASE = "network status is offline"
const val NETWORK_EXCEPTION_BODY_IS_NULL = "result body is null"

@Provides
@Singleton
fun provideOKHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(HttpRequestInterceptor())
.retryOnConnectionFailure(false)
.build()
}

@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.client(okHttpClient)
.baseUrl(OworiApplication.getString(R.string.base_url))
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
}

@Provides
@Singleton
fun provideAuthApi(retrofit: Retrofit): AuthApi {
return retrofit.buildService()
}

private inline fun <reified T> Retrofit.buildService(): T {
return this.create(T::class.java)
}
}
9 changes: 9 additions & 0 deletions app/src/main/java/com/owori/android/data/api/auth/AuthApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.owori.android.data.api.auth

/*
* Created by JJJoonngg
*/

interface AuthApi {

}
41 changes: 41 additions & 0 deletions app/src/main/java/com/owori/android/module/DataResult.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.owori.android.module

/*
* Created by JJJoonngg
*/

sealed class DataResult<out T> {
data class Success<T>(val data: T) : DataResult<T>()
data class Fail(val statusCode: Int, val message: String) : DataResult<Nothing>()
data class Error(val exception: Exception) : DataResult<Nothing>()
}

inline fun <T> DataResult<T>.onSuccess(action: (T) -> Unit): DataResult<T> {
if (this is DataResult.Success) {
action(data)
}
return this
}

inline fun <T> DataResult<T>.onFail(resultCode: (Int) -> Unit): DataResult<T> {
if (this is DataResult.Fail) {
resultCode(this.statusCode)
}
return this
}

inline fun <T> DataResult<T>.onError(action: (Exception) -> Unit): DataResult<T> {
if (this is DataResult.Fail) {
action(IllegalArgumentException("code : ${this.statusCode}, message : ${this.message}"))
} else if (this is DataResult.Error) {
action(this.exception)
}
return this
}

inline fun <T> DataResult<T>.onException(action: (Exception) -> Unit): DataResult<T> {
if (this is DataResult.Error) {
action(this.exception)
}
return this
}
41 changes: 41 additions & 0 deletions app/src/main/java/com/owori/android/module/HandleApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.owori.android.module

import com.owori.android.core.OworiApplication
import com.owori.android.core.di.NetworkModule
import retrofit2.Response

/*
* Created by JJJoonngg
*/

suspend fun <T : Any, R : Any> handleApi(
execute: suspend () -> Response<T>,
mapper: (T) -> R
): DataResult<R> {
if (OworiApplication.isOnline().not()) {
return DataResult.Error(Exception(NetworkModule.NETWORK_EXCEPTION_OFFLINE_CASE))
}

return try {
val response = execute()
val body = response.body()
if (response.isSuccessful) {
body?.let {
DataResult.Success(mapper(it))
} ?: run {
throw NullPointerException(NetworkModule.NETWORK_EXCEPTION_BODY_IS_NULL)
}
} else {
getFailDataResult(body, response)
}
} catch (e: Exception) {
DataResult.Error(e)
}
}


private fun <T : Any> getFailDataResult(body: T?, response: Response<T>) = body?.let {
DataResult.Fail(statusCode = response.code(), message = it.toString())
} ?: run {
DataResult.Fail(statusCode = response.code(), message = response.message())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.owori.android.module

import android.util.Log
import com.owori.android.core.AppConfig
import okhttp3.Interceptor
import okhttp3.Response


class HttpRequestInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
try {
val originRequest = chain.request()
Log.d(AppConfig.TAG_DEBUG, "HttpRequestInterceptor: ${originRequest.url}")

return chain.proceed(originRequest)
} catch (e: Exception) {
Log.d(AppConfig.TAG_DEBUG, "HttpRequestInterceptor error: ${e.message}")
throw e
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.owori.android.module

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.NetworkRequest

/*
* Created by JJJoonngg
*/

class NetworkConnectionChecker(context: Context) : ConnectivityManager.NetworkCallback() {

private val networkRequest: NetworkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build()
private val connectivityManager: ConnectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

fun register() {
connectivityManager.registerNetworkCallback(networkRequest, this)
}

fun unregister() {
connectivityManager.unregisterNetworkCallback(this)
}

fun isOnline(): Boolean {
val nw = connectivityManager.activeNetwork ?: return false
val actNw = connectivityManager.getNetworkCapabilities(nw) ?: return false
return when {
actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
else -> false
}
}
}
4 changes: 4 additions & 0 deletions app/src/main/res/values/constants.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="base_url">http://owori.store/api/v1</string>
</resources>
13 changes: 9 additions & 4 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,16 @@ espresso-core = { group = "androidx.test.espresso", name = "espresso-core", vers
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }

kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinxCoroutines" }
okhttp-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp"}
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit"}

okhttp-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" }
retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
retrofit-kotlin-serialization = { group = "com.jakewharton.retrofit", name = "retrofit2-kotlinx-serialization-converter", version.ref = "retrofitKotlinxSerializationJson" }
retrofit-converter-gson = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit" }
retrofit-converter-scalars = { group = "com.squareup.retrofit2", name = "converter-scalars", version.ref = "retrofit" }

work-runtime = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work-runtime" }
support-compat = { group = "com.android.support", name = "support-compat", version.ref = "support-compat" }
coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "coroutines-core" }
Expand All @@ -68,8 +73,8 @@ lottie = { group = "com.airbnb.android", name = "lottie", version.ref = "lottie-
androidx-work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "workRuntimeKtx" }
identity-credential = { group = "com.android.identity", name = "identity-credential", version = "20230420" }
firebase-bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebase-bom" }
firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics-ktx"}
firebase-analytics = { group = "com.google.firebase", name = "firebase-analytics-ktx"}
firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics-ktx" }
firebase-analytics = { group = "com.google.firebase", name = "firebase-analytics-ktx" }
firebase-auth = { group = "com.google.firebase", name = "firebase-auth-ktx" }
play-service-auth = { group = "com.google.android.gms", name = "play-services-auth", version.ref = "play-service-auth" }
dagger-hilt = { group = "com.google.dagger", name = "hilt-android", version.ref = "dagger-hilt" }
Expand Down

0 comments on commit f5b4fbf

Please # to comment.