diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 75afb311..79fceb1f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,13 +2,14 @@
-
-
-
+
+
+
-
+
-
+ android:value="${KAKAO_NATIVE_KEY}" />
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/paw/key/PawKeyApplication.kt b/app/src/main/java/com/paw/key/PawKeyApplication.kt
index 1b02e4c7..eb67c810 100644
--- a/app/src/main/java/com/paw/key/PawKeyApplication.kt
+++ b/app/src/main/java/com/paw/key/PawKeyApplication.kt
@@ -7,6 +7,7 @@ import coil.ImageLoaderFactory
import coil.disk.DiskCache
import coil.memory.MemoryCache
import coil.util.DebugLogger
+import com.kakao.sdk.common.KakaoSdk
import com.kakao.vectormap.KakaoMapSdk
import com.naver.maps.map.NaverMapSdk
import dagger.hilt.android.HiltAndroidApp
@@ -22,10 +23,10 @@ class PawKeyApplication : Application(), ImageLoaderFactory {
override fun onCreate() {
super.onCreate()
-
setTimber()
setDarkMode()
+ KakaoSdk.init(this, kakaoNativeKey)
KakaoMapSdk.init(this, kakaoNativeKey)
NaverMapSdk.getInstance(this).client =
NaverMapSdk.NcpKeyClient(BuildConfig.NAVERMAP_CLIENT_ID)
diff --git a/app/src/main/java/com/paw/key/data/di/RepositoryModule.kt b/app/src/main/java/com/paw/key/data/di/RepositoryModule.kt
index 925dbcea..9733454a 100644
--- a/app/src/main/java/com/paw/key/data/di/RepositoryModule.kt
+++ b/app/src/main/java/com/paw/key/data/di/RepositoryModule.kt
@@ -22,8 +22,10 @@ import com.paw.key.data.repositoryimpl.walklist.WalkListDetailRepositoryImpl
import com.paw.key.data.repositoryimpl.walkreview.WalkReviewRepositoryImpl
import com.paw.key.data.remote.datasource.datasourceimpl.AuthRemoteDataSourceImpl
import com.paw.key.data.remote.datasource.datasourceimpl.GoogleAuthDataSourceImpl
+import com.paw.key.data.remote.datasource.datasourceimpl.KakaoAuthDataSourceImpl
import com.paw.key.data.remote.datasource.login.AuthRemoteDataSource
import com.paw.key.data.remote.datasource.login.GoogleAuthDataSource
+import com.paw.key.data.remote.datasource.login.KakaoAuthDataSource
import com.paw.key.domain.repository.ArchivedListRepository
import com.paw.key.domain.repository.DummyRepository
import com.paw.key.domain.repository.LikeRepository
@@ -66,6 +68,11 @@ interface RepositoryModule {
impl: GoogleAuthDataSourceImpl,
): GoogleAuthDataSource
+ @Binds
+ abstract fun bindKakaoAuthDataSource(
+ impl: KakaoAuthDataSourceImpl
+ ): KakaoAuthDataSource
+
@Binds
fun bindsDummyRepository(
dummyRepositoryImpl: DummyRepositoryImpl
diff --git a/app/src/main/java/com/paw/key/data/remote/datasource/datasourceimpl/AuthRemoteDataSourceImpl.kt b/app/src/main/java/com/paw/key/data/remote/datasource/datasourceimpl/AuthRemoteDataSourceImpl.kt
index 053f3b68..67cbf527 100644
--- a/app/src/main/java/com/paw/key/data/remote/datasource/datasourceimpl/AuthRemoteDataSourceImpl.kt
+++ b/app/src/main/java/com/paw/key/data/remote/datasource/datasourceimpl/AuthRemoteDataSourceImpl.kt
@@ -1,14 +1,13 @@
package com.paw.key.data.remote.datasource.datasourceimpl
import com.paw.key.data.dto.request.LoginRequestDto
-import com.paw.key.data.dto.response.BaseResponse
import com.paw.key.data.dto.response.LoginResponseDto
import com.paw.key.data.remote.datasource.login.AuthRemoteDataSource
import com.paw.key.data.service.login.LoginService
import javax.inject.Inject
class AuthRemoteDataSourceImpl @Inject constructor(
- private val loginService: LoginService
+ private val loginService: LoginService,
) : AuthRemoteDataSource {
override suspend fun login(idToken: String, deviceId: String): LoginResponseDto {
return loginService.login(
@@ -18,4 +17,13 @@ class AuthRemoteDataSourceImpl @Inject constructor(
)
)
}
+
+ override suspend fun loginKakao(idToken: String, deviceId: String): LoginResponseDto {
+ return loginService.loginKakao(
+ LoginRequestDto(
+ idToken = idToken,
+ deviceId = deviceId
+ )
+ )
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/paw/key/data/remote/datasource/datasourceimpl/KakaoAuthDataSourceImpl.kt b/app/src/main/java/com/paw/key/data/remote/datasource/datasourceimpl/KakaoAuthDataSourceImpl.kt
new file mode 100644
index 00000000..7afaa3f9
--- /dev/null
+++ b/app/src/main/java/com/paw/key/data/remote/datasource/datasourceimpl/KakaoAuthDataSourceImpl.kt
@@ -0,0 +1,60 @@
+package com.paw.key.data.remote.datasource.datasourceimpl
+
+import android.content.Context
+import com.kakao.sdk.auth.model.OAuthToken
+import com.kakao.sdk.common.model.ClientError
+import com.kakao.sdk.common.model.ClientErrorCause
+import com.kakao.sdk.user.UserApiClient
+import com.paw.key.core.util.suspendRunCatching
+import com.paw.key.data.remote.datasource.login.KakaoAuthDataSource
+import kotlinx.coroutines.suspendCancellableCoroutine
+import javax.inject.Inject
+import kotlin.coroutines.resume
+import kotlin.coroutines.resumeWithException
+
+class KakaoAuthDataSourceImpl @Inject constructor() : KakaoAuthDataSource {
+ override suspend fun signIn(context: Context): Result = suspendRunCatching {
+ val accessToken = getKakaoAccessToken(context)
+ accessToken
+ }
+
+ private suspend fun getKakaoAccessToken(context: Context): String =
+ suspendCancellableCoroutine { continuation ->
+ val callback: (OAuthToken?, Throwable?) -> Unit = { token, error ->
+ when {
+ error != null -> {
+ continuation.resumeWithException(error)
+ }
+ token != null -> {
+ continuation.resume(token.accessToken)
+ }
+ else -> {
+ continuation.resumeWithException(
+ IllegalStateException("Token and error are both null")
+ )
+ }
+ }
+ }
+
+ if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) {
+ UserApiClient.instance.loginWithKakaoTalk(context) { token, error ->
+ if (error is ClientError && error.reason == ClientErrorCause.Cancelled) {
+ continuation.resumeWithException(error)
+ return@loginWithKakaoTalk
+ }
+ when {
+ token != null -> callback(token, null)
+ error != null -> {
+ UserApiClient.instance.loginWithKakaoAccount(
+ context,
+ callback = callback
+ )
+ }
+ }
+ }
+ } else {
+ UserApiClient.instance.loginWithKakaoAccount(context, callback = callback)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/paw/key/data/remote/datasource/login/AuthRemoteDataSource.kt b/app/src/main/java/com/paw/key/data/remote/datasource/login/AuthRemoteDataSource.kt
index 3a5849bf..c674c39e 100644
--- a/app/src/main/java/com/paw/key/data/remote/datasource/login/AuthRemoteDataSource.kt
+++ b/app/src/main/java/com/paw/key/data/remote/datasource/login/AuthRemoteDataSource.kt
@@ -5,4 +5,6 @@ import com.paw.key.data.dto.response.LoginResponseDto
interface AuthRemoteDataSource {
suspend fun login(idToken: String, deviceId: String): LoginResponseDto
+
+ suspend fun loginKakao(idToken: String, deviceId: String): LoginResponseDto
}
\ No newline at end of file
diff --git a/app/src/main/java/com/paw/key/data/remote/datasource/login/KakaoAuthDataSource.kt b/app/src/main/java/com/paw/key/data/remote/datasource/login/KakaoAuthDataSource.kt
new file mode 100644
index 00000000..f14b643f
--- /dev/null
+++ b/app/src/main/java/com/paw/key/data/remote/datasource/login/KakaoAuthDataSource.kt
@@ -0,0 +1,7 @@
+package com.paw.key.data.remote.datasource.login
+
+import android.content.Context
+
+interface KakaoAuthDataSource {
+ suspend fun signIn(context: Context): Result
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/paw/key/data/repositoryimpl/login/AuthRepositoryImpl.kt b/app/src/main/java/com/paw/key/data/repositoryimpl/login/AuthRepositoryImpl.kt
index 8cd8095a..79718d8b 100644
--- a/app/src/main/java/com/paw/key/data/repositoryimpl/login/AuthRepositoryImpl.kt
+++ b/app/src/main/java/com/paw/key/data/repositoryimpl/login/AuthRepositoryImpl.kt
@@ -6,6 +6,7 @@ import com.paw.key.core.util.suspendRunCatching
import com.paw.key.data.dto.response.LoginResponseDto
import com.paw.key.data.remote.datasource.login.AuthRemoteDataSource
import com.paw.key.data.remote.datasource.login.GoogleAuthDataSource
+import com.paw.key.data.remote.datasource.login.KakaoAuthDataSource
import com.paw.key.domain.repository.login.AuthRepository
import dagger.hilt.android.qualifiers.ApplicationContext
import timber.log.Timber
@@ -14,26 +15,32 @@ import javax.inject.Inject
class AuthRepositoryImpl @Inject constructor(
private val authRemoteDataSource: AuthRemoteDataSource,
private val googleAuthDataSource: GoogleAuthDataSource,
+ private val kakaoAuthDataSource: KakaoAuthDataSource,
@ApplicationContext private val context: Context
) : AuthRepository {
override suspend fun signInWithGoogle(context: Context): Result =
googleAuthDataSource.signIn(context).map { it.idToken }
+ override suspend fun signInWithKakao(context: Context): Result =
+ kakaoAuthDataSource.signIn(context)
+
override suspend fun login(idToken: String, deviceId: String): Result =
suspendRunCatching {
-
val loginResponse = authRemoteDataSource.login(idToken, deviceId)
+ saveTokens(loginResponse)
+ loginResponse
+ }
- UserDataStore.saveAcessToken(
- context = this.context,
- token = loginResponse.accessToken
- )
- UserDataStore.saveRefreshToken(
- context = this.context,
- token = loginResponse.refreshToken
- )
-
+ override suspend fun loginKakao(idToken: String, deviceId: String): Result =
+ suspendRunCatching {
+ val loginResponse = authRemoteDataSource.loginKakao(idToken, deviceId)
+ saveTokens(loginResponse)
loginResponse
}
+
+ private suspend fun saveTokens(loginResponse: LoginResponseDto) {
+ UserDataStore.saveAcessToken(context, loginResponse.accessToken)
+ UserDataStore.saveRefreshToken(context, loginResponse.refreshToken)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/paw/key/data/service/login/LoginService.kt b/app/src/main/java/com/paw/key/data/service/login/LoginService.kt
index f6e953d4..7baacd31 100644
--- a/app/src/main/java/com/paw/key/data/service/login/LoginService.kt
+++ b/app/src/main/java/com/paw/key/data/service/login/LoginService.kt
@@ -13,4 +13,9 @@ interface LoginService {
suspend fun login(
@Body loginRequestDto: LoginRequestDto
): LoginResponseDto
+
+ @POST("auth/kakao/login")
+ suspend fun loginKakao(
+ @Body loginRequestDto: LoginRequestDto
+ ): LoginResponseDto
}
\ No newline at end of file
diff --git a/app/src/main/java/com/paw/key/domain/repository/login/AuthRepository.kt b/app/src/main/java/com/paw/key/domain/repository/login/AuthRepository.kt
index 6791bf6f..bbf771d4 100644
--- a/app/src/main/java/com/paw/key/domain/repository/login/AuthRepository.kt
+++ b/app/src/main/java/com/paw/key/domain/repository/login/AuthRepository.kt
@@ -5,5 +5,7 @@ import com.paw.key.data.dto.response.LoginResponseDto
interface AuthRepository {
suspend fun signInWithGoogle(context: Context): Result
+ suspend fun signInWithKakao(context: Context): Result
suspend fun login(idToken: String, deviceId: String): Result
+ suspend fun loginKakao(idToken: String, deviceId: String): Result
}
\ No newline at end of file
diff --git a/app/src/main/java/com/paw/key/presentation/ui/login/LoginScreen.kt b/app/src/main/java/com/paw/key/presentation/ui/login/LoginScreen.kt
index ec8f8c10..15add237 100644
--- a/app/src/main/java/com/paw/key/presentation/ui/login/LoginScreen.kt
+++ b/app/src/main/java/com/paw/key/presentation/ui/login/LoginScreen.kt
@@ -27,6 +27,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@@ -143,12 +144,18 @@ fun LoginScreen(
Image(
painter = painterResource(R.drawable.img_login_sub),
contentDescription = stringResource(R.string.ic_login_sub_image),
+ contentScale = ContentScale.Crop,
)
LoginSocialButton(
logo = R.drawable.ic_login_kakao,
loginText = stringResource(R.string.ic_login_kakao),
- onClick = {},
+ onClick = {
+ viewModel.onKakaoSignIn(
+ context = context,
+ onSuccess = navigateHome
+ )
+ },
modifier = Modifier
.background(
shape = RoundedCornerShape(12.dp),
diff --git a/app/src/main/java/com/paw/key/presentation/ui/login/viewmodel/LoginViewModel.kt b/app/src/main/java/com/paw/key/presentation/ui/login/viewmodel/LoginViewModel.kt
index b1959ab6..a5678f62 100644
--- a/app/src/main/java/com/paw/key/presentation/ui/login/viewmodel/LoginViewModel.kt
+++ b/app/src/main/java/com/paw/key/presentation/ui/login/viewmodel/LoginViewModel.kt
@@ -50,6 +50,28 @@ class LoginViewModel @Inject constructor(
}
}
+ fun onKakaoSignIn(
+ context: Context,
+ onSuccess: () -> Unit,
+ ) {
+ viewModelScope.launch {
+ authRepository.signInWithKakao(context)
+ .onSuccess { accessToken ->
+ val deviceId = getDeviceId(context)
+ authRepository.loginKakao(accessToken, deviceId)
+ .onSuccess { response ->
+ onSuccess()
+ }
+ .onFailure { e ->
+ Timber.e(e, "Full stack trace:")
+ }
+ }
+ .onFailure { e ->
+ Timber.e("[KAKAO_VM] Step 2: SDK login FAILED")
+ }
+ }
+ }
+
private fun getDeviceId(context: Context): String {
return android.provider.Settings.Secure.getString(
context.contentResolver,