diff --git a/app/build.gradle b/app/build.gradle
index 57ebd699..b5d24897 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -78,6 +78,8 @@ dependencies {
implementation 'com.jakewharton.threetenabp:threetenabp:1.4.4'
implementation 'com.prolificinteractive:material-calendarview:1.4.3'
implementation 'androidx.recyclerview:recyclerview:1.3.0'
+ implementation 'com.google.android.datatransport:transport-runtime:3.1.2'
+ implementation 'com.google.android.gms:play-services-base:18.0.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
@@ -108,4 +110,10 @@ dependencies {
// implementation group: 'com.kakao.sdk', name: 'kakaolink', version: '1.30.5'
implementation "com.kakao.sdk:v2-user:2.5.0" // 카카오 로그인
+
+ implementation 'com.google.dagger:hilt-android:2.47'
+ annotationProcessor 'com.google.dagger:hilt-compiler:2.47'
+
+// implementation "androidx.security:security-crypto:1.0.0"
+
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 37cac08e..07d27879 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -16,40 +16,41 @@
+
+
+
-
-
-
-
+ android:value="$kakao_native_app_key" />
+
+
@@ -58,11 +59,11 @@
+
-
-
@@ -89,13 +89,14 @@
+ android:exported="true"
+ android:windowSoftInputMode="adjustResize">
+
@@ -109,6 +110,7 @@
+
@@ -122,11 +124,11 @@
+
-
@@ -179,11 +181,11 @@
android:exported="true"
android:windowSoftInputMode="adjustResize">
-
+
diff --git a/app/src/main/java/com/eatssu/android/data/RefreshTokenService.kt b/app/src/main/java/com/eatssu/android/data/RefreshTokenService.kt
new file mode 100644
index 00000000..42ffceaa
--- /dev/null
+++ b/app/src/main/java/com/eatssu/android/data/RefreshTokenService.kt
@@ -0,0 +1,24 @@
+package com.eatssu.android.data
+
+import RetrofitImpl.retrofit
+import com.eatssu.android.App
+import com.eatssu.android.data.service.UserService
+
+object RefreshTokenService {
+
+ private val userService = retrofit.create(UserService::class.java)
+
+ fun refreshToken(): String {
+ val res = userService.getNewToken().execute()
+ if (res.isSuccessful) {
+ val newAccessToken = res.body()?.accessToken ?: ""
+ val newRefreshToken = res.body()?.refreshToken ?: ""
+ if (newAccessToken.isNotBlank()) {
+ App.token_prefs.accessToken = newAccessToken
+ App.token_prefs.refreshToken = newRefreshToken
+ return newAccessToken
+ }
+ }
+ throw IllegalStateException("토큰 재발급 실패")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/eatssu/android/data/RetrofitImpl.kt b/app/src/main/java/com/eatssu/android/data/RetrofitImpl.kt
index 9c771267..bd9c1ca1 100644
--- a/app/src/main/java/com/eatssu/android/data/RetrofitImpl.kt
+++ b/app/src/main/java/com/eatssu/android/data/RetrofitImpl.kt
@@ -1,5 +1,6 @@
import com.eatssu.android.App
import com.eatssu.android.BuildConfig
+import com.eatssu.android.data.TokenAuthenticator
import okhttp3.*
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
@@ -48,6 +49,7 @@ object RetrofitImpl {
OkHttpClient.Builder()
.addInterceptor(httpLoggingInterceptor)
.addInterceptor(AppInterceptor())
+ .authenticator(TokenAuthenticator())
.build()
}
diff --git a/app/src/main/java/com/eatssu/android/data/TokenAuthenticator.kt b/app/src/main/java/com/eatssu/android/data/TokenAuthenticator.kt
index c5289fc8..9b2432e8 100644
--- a/app/src/main/java/com/eatssu/android/data/TokenAuthenticator.kt
+++ b/app/src/main/java/com/eatssu/android/data/TokenAuthenticator.kt
@@ -1,102 +1,25 @@
package com.eatssu.android.data
-import android.content.Context
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.async
-import kotlinx.coroutines.runBlocking
+import android.util.Log
import okhttp3.Authenticator
import okhttp3.Request
import okhttp3.Response
import okhttp3.Route
-import retrofit2.Retrofit
-//class TokenAuthenticator constructor(
-// val context: Context,
-// private val refreshToken: String,
-//) : Authenticator {
-//
-// companion object {
-// private val TAG = TokenAuthenticator::class.java.simpleName
-// }
-//
-// override fun authenticate(route: Route?, response: Response): Request? {
-//
-// if (response.code == 401) {
-//
-// val refreshToken = CommonHelper.getRefreshToken(sharedPref)
-// val getNewDeviceToken = GlobalScope.async(Dispatchers.Default) {
-// getNewDeviceToken(refreshToken)
-// }
-//
-// val token = runBlocking {
-// getNewDeviceToken.await()
-// }
-// if(token != null) {
-// return getRequest(response, token)
-// }
-// }
-// return null
-// }
-//
-// private suspend inline fun getNewDeviceToken(token: String): String? {
-// return GlobalScope.async(Dispatchers.Default) {
-// callApiNewDeviceToken(token)
-// }.await()
-// }
-//
-//
-// private suspend inline fun callApiNewDeviceToken(token: String) : String? = suspendCoroutine { continuation ->
-// createWebService()
-// .refreshToken(RefreshToken(token))
-// .with(rx)
-// .response(object : ApiCallback{
-// override fun success(data: Token?) {
-// if(data != null) {
-// CommonHelper.saveTokenInfo(sharedPref, data)
-// continuation.resume(data.accessToken)
-// } else {
-// continuation.resume(null)
-// }
-// }
-//
-// override fun error(statusCode: Int, message: String?) {
-// continuation.resume(null)
-// }
-// })
-//
-// return@suspendCoroutine
-// }
-//
-// private val okHttp = OkHttpClient.Builder()
-// .connectTimeout(TIMEOUT_LIMIT, TimeUnit.SECONDS)
-// .readTimeout(TIMEOUT_LIMIT, TimeUnit.SECONDS)
-// .writeTimeout(TIMEOUT_LIMIT, TimeUnit.SECONDS)
-// .addInterceptor(HttpLoggingInterceptor().apply {
-// level = if (BuildConfig.DEBUG) {
-// HttpLoggingInterceptor.Level.BODY
-// } else {
-// HttpLoggingInterceptor.Level.NONE
-// }
-// })
-// .build()
-//
-// private inline fun createWebService(): T {
-// val retrofit = Retrofit.Builder()
-// .baseUrl(BuildConfig.SERVER_URL)
-// .client(okHttp)
-// .addConverterFactory(GsonConverterFactory.create(
-// GsonBuilder().serializeNulls().create()
-// ))
-// .addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build()
-// return retrofit.create(T::class.java)
-// }
-//
-// private fun getRequest(response: Response, token: String): Request {
-// return response.request
-// .newBuilder()
-// .removeHeader("Authorization")
-// .addHeader("Authorization", "Bearer $token")
-// .build()
-// }
-//}
\ No newline at end of file
+class TokenAuthenticator: Authenticator {
+ override fun authenticate(route: Route?, response: Response): Request? {
+ Log.i("Authenticator", response.toString())
+ Log.i("Authenticator", "토큰 재발급 시도")
+ return try {
+ val newAccessToken = RefreshTokenService.refreshToken()
+ Log.i("Authenticator", "토큰 재발급 성공 : $newAccessToken")
+ response.request.newBuilder()
+ .removeHeader("Bearer").apply {
+ addHeader("Bearer", newAccessToken)
+ }.build() // 토큰 재발급이 성공했다면, 기존 헤더를 지우고, 새로운 해더를 단다.
+ } catch (e: Exception) {
+ e.printStackTrace()
+ null // 만약 토큰 재발급이 실패했다면 헤더에 아무것도 추가하지 않는다.
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/eatssu/android/ui/login/SocialLoginActivity.kt b/app/src/main/java/com/eatssu/android/ui/login/SocialLoginActivity.kt
index 638ef6a7..fe129f22 100644
--- a/app/src/main/java/com/eatssu/android/ui/login/SocialLoginActivity.kt
+++ b/app/src/main/java/com/eatssu/android/ui/login/SocialLoginActivity.kt
@@ -11,6 +11,7 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.eatssu.android.App
+import com.eatssu.android.data.MySharedPreferences
import com.eatssu.android.data.model.request.loginWithKakaoRequest
import com.eatssu.android.data.model.response.TokenResponse
import com.eatssu.android.data.service.OauthService
@@ -69,6 +70,31 @@ class SocialLoginActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
binding = ActivitySocialLoginBinding.inflate(layoutInflater)
setContentView(binding.root)
+
+ //카카오 로그인에서 제공하는 자동로그인 메소드
+// UserApiClient.instance.accessTokenInfo { tokenInfo, error ->
+// if (error != null) {
+// Toast.makeText(this, "자동 로그인 실패", Toast.LENGTH_SHORT).show()
+// }
+// else if (tokenInfo != null) {
+// Toast.makeText(this, "자동 로그인 성공", Toast.LENGTH_SHORT).show()
+// val intent = Intent(this, MainActivity::class.java)
+// startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
+// }
+// }
+
+ // SharedPreferences 안에 값이 저장되어 있을 때-> Login 패스하기
+ if (App.token_prefs.accessToken?.isNotBlank() == true){ // SharedPreferences 안에 값이 저장되어 있을 때 -> MainActivity로 이동
+ Toast.makeText(
+ this,
+ "자동 로그인 되었습니다.",
+ Toast.LENGTH_SHORT
+ ).show()
+ val intent = Intent(this, MainActivity::class.java)
+ startActivity(intent)
+ finish()
+ }
+
val context = this
binding.imbKakao.setOnClickListener {
lifecycleScope.launch {
diff --git a/app/src/main/java/com/eatssu/android/ui/login/UserApiClientExt.kt b/app/src/main/java/com/eatssu/android/ui/login/UserApiClient.kt
similarity index 100%
rename from app/src/main/java/com/eatssu/android/ui/login/UserApiClientExt.kt
rename to app/src/main/java/com/eatssu/android/ui/login/UserApiClient.kt