Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat/kakao_login]: 카카오 소셜 로그인, 닉네임 불러오기, 로그아웃 구현 #30

Merged
merged 36 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
e24b7b1
[setting]: Fix Merge Error
kez-lab Dec 30, 2023
f0b04fe
[feat]: Feat Login Module
kez-lab Dec 30, 2023
cb31fcc
[feat]: Feat SampleClass
kez-lab Dec 30, 2023
9c0bafe
[setting]: 카카오 sdk 추가
kangyuri1114 Dec 30, 2023
deb2ece
[setting]: 카카오 sdk 추가
kangyuri1114 Dec 31, 2023
7c140d3
[feat]: 인터넷 권한 허용
kangyuri1114 Jan 1, 2024
9ec42cf
[fix]: Debug KeyStore
kez-lab Jan 1, 2024
e5ff432
Merge remote-tracking branch 'origin/feat/kakao_login' into feat/kaka…
kangyuri1114 Jan 1, 2024
b29e663
[feat]: LoginActivity 생성
kangyuri1114 Jan 1, 2024
6991738
[delete]: sampleClass 삭제
kangyuri1114 Jan 1, 2024
394008b
[feat]: LoginActivity viewBinding
kangyuri1114 Jan 1, 2024
afdd143
[feat]: local properties에 KAKAO_NATIVE_APP_KEY 추가
kangyuri1114 Jan 1, 2024
9c95a29
[feat]: 로그인 조합 예제 함수 삽입
kangyuri1114 Jan 1, 2024
84af8ad
[feat]: LoginViewModel 생성
kangyuri1114 Jan 1, 2024
46f8344
[feat]: 카카오 로그인 기능 구현 (앱, 웹)
kangyuri1114 Jan 2, 2024
2c56cdf
[feat]: 로그인 성공 시 유저 정보 반환 액티비티 생성 및 세팅
kangyuri1114 Jan 2, 2024
c3941f6
[feat]: 유저 닉네임 반환, 카카오 로그아웃 기능 구현
kangyuri1114 Jan 2, 2024
74c9e8f
[refact]: 카카오 로그인 코드 리팩토링
kangyuri1114 Jan 2, 2024
3bc8510
[fix]: Fix Navigation Resource
kez-lab Jan 2, 2024
3b8cbf4
[fix]: Fix Common Dependency
kez-lab Jan 2, 2024
27d78da
Merge remote-tracking branch 'origin/develop' into develop
kangyuri1114 Jan 2, 2024
c70cb1c
[fix]: resolve conflict
kangyuri1114 Jan 2, 2024
eb2e8f6
[fix]: resolve conflict
kangyuri1114 Jan 2, 2024
3e804a1
[feat]: viewModel, Livedata 세팅
kangyuri1114 Jan 2, 2024
dcb394e
[fix]: Fix Kakao Api Key
kez-lab Jan 3, 2024
8f61225
[feat]: 카카오 로그인 버튼 추가
kangyuri1114 Jan 3, 2024
cde45aa
[feat]: 로그인 컨셉설명 뷰페이저 UI 구현
kangyuri1114 Jan 3, 2024
74bf456
[delete]: 프래그먼트 파일 삭제
kangyuri1114 Jan 3, 2024
5b5c5b0
[feat]: 로그인 화면 뷰페이저 구현
kangyuri1114 Jan 3, 2024
cbcd38d
[fix]: Fix properties reference
kez-lab Jan 3, 2024
8b196a6
Merge branch 'feat/login_view' into feat/kakao_login
kangyuri1114 Jan 3, 2024
f39c00e
[fix]: indicator 색 변경
kangyuri1114 Jan 3, 2024
811a6d5
[fix]: id 명 변경
kangyuri1114 Jan 3, 2024
acb4224
[fix]: id 명 변경
kangyuri1114 Jan 3, 2024
66850b4
[fix]: 뷰페이저 함수화
kangyuri1114 Jan 3, 2024
75aa724
[fix]: 뷰페이저 함수화
kangyuri1114 Jan 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/develop_PR_builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ jobs:
- name: Change gradlew permissions
run: chmod +x ./gradlew

- name: Add Local Properties
env:
KAKAO_API_KEY: ${{ secrets.KAKAO_API_KEY }}
run: |
echo kakaoApiKey=$KAKAO_API_KEY >> ./local.properties

- name: Access Firebase Service
run: echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > ./app/google-services.json

Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ render.experimental.xml

# Keystore files
*.jks
*.keystore

# Google Services (e.g. APIs or Firebase)
google-services.json
Expand Down
32 changes: 22 additions & 10 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,23 @@ android {
versionName = libs.versions.appVersion.get()
}

signingConfigs {
getByName("debug") {
keyAlias = "android_debug_key"
keyPassword = "android"
storeFile = File("${project.rootDir.absolutePath}/keystore/debug.keystore")
storePassword = "android"
}
}

buildTypes {
debug {
isDebuggable = true
signingConfig = signingConfigs.getByName("debug")
}
release {
isMinifyEnabled = false
isDebuggable = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
Expand All @@ -28,21 +42,19 @@ android {
}

dependencies {
// Feature
implementation(projects.feature.onboarding)

// Core
implementation(projects.core.common)
implementation(projects.core.database)

// Feature
implementation(projects.feature.onboarding)
implementation(projects.feature.main)

// Firebase
implementation(platform(libs.firebase))
implementation(libs.bundles.firebase)

// Splash
implementation(libs.splash.screen)

// Features
implementation(projects.feature.login)
implementation(projects.feature.onboarding)
implementation(projects.feature.main)

// kakao
implementation(libs.kakao.login)
}
18 changes: 18 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
Expand All @@ -21,8 +23,24 @@
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>
</activity>

<activity
android:name="com.kakao.sdk.auth.AuthCodeHandlerActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:host="oauth"
android:scheme="kakao${kakaoApiKey}" />
</intent-filter>
</activity>


</application>

</manifest>
11 changes: 9 additions & 2 deletions app/src/main/java/com/hmh/hamyeonham/SampleActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import android.view.animation.AnimationUtils
import androidx.appcompat.app.AppCompatActivity
import androidx.core.splashscreen.SplashScreen
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import com.hmh.hamyeonham.feature.login.LoginActivity
import com.kakao.sdk.common.KakaoSdk
import com.hmh.hamyeonham.feature.main.MainActivity
import com.hmh.hamyeonham.feature.onboarding.OnBoardingActivity

class SampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Expand All @@ -18,7 +19,13 @@ class SampleActivity : AppCompatActivity() {
initSplashAnimation(splashScreen)

setContentView(R.layout.activity_sample)
Intent(this, MainActivity::class.java).let(::startActivity)

initKakaoSdk()
Intent(this, LoginActivity::class.java).let(::startActivity)
}

private fun initKakaoSdk() {
KakaoSdk.init(this, BuildConfig.KAKAO_API_KEY)
}

private fun initSplashAnimation(splashScreen: SplashScreen) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import java.util.Properties

internal fun Project.configureAndroidCommonPlugin() {

val properties = Properties().apply {
load(rootProject.file("local.properties").inputStream())
}

apply<AndroidKotlinPlugin>()
apply<KotlinSerializationPlugin>()
with(plugins) {
Expand All @@ -18,7 +22,13 @@ internal fun Project.configureAndroidCommonPlugin() {
apply<AndroidHiltPlugin>()

extensions.getByType<BaseExtension>().apply {
defaultConfig {}
defaultConfig {
val kakaoApiKey = properties["kakaoApiKey"] as? String ?: ""

manifestPlaceholders["kakaoApiKey"] = properties["kakaoApiKey"] as String

buildConfigField("String", "KAKAO_API_KEY", "\"${kakaoApiKey}\"")
}
buildFeatures.apply {
viewBinding = true
buildConfig = true
Expand Down
1 change: 1 addition & 0 deletions feature/login/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
22 changes: 22 additions & 0 deletions feature/login/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
plugins {
hmh("feature")
alias(libs.plugins.kotlin.android)
}

android {
namespace = "com.hmh.hamyeonham.feature.login"
}

dependencies {
implementation(projects.core.common)
implementation(libs.appcompat)
implementation(libs.material)
implementation(libs.constraintlayout)

// kakao
implementation(libs.kakao.login)

implementation(libs.dot.indicator)
implementation(libs.coil.core)
}
Empty file.
21 changes: 21 additions & 0 deletions feature/login/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
13 changes: 13 additions & 0 deletions feature/login/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application>
<activity
android:name=".UserInfoActivity"
android:exported="false" />
<activity
android:name=".LoginActivity"
android:exported="false" />
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.hmh.hamyeonham.feature.login

import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import com.hmh.hamyeonham.common.context.toast
import com.hmh.hamyeonham.feature.login.data.DummyImage
import com.hmh.hamyeonham.feature.login.databinding.ActivityLoginBinding
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

class LoginActivity : AppCompatActivity() {
private lateinit var binding: ActivityLoginBinding

private val loginViewModel: LoginViewModel by viewModels()
private lateinit var loginViewPagerAdapter: LoginViewPagerAdapter

// 삭제 예정
private val dummyImageList = listOf(
DummyImage(
Image = R.drawable.login_sample_rectagle_viewpager,
),
DummyImage(
Image = R.drawable.login_sample_rectagle_viewpager,
),
DummyImage(
Image = R.drawable.login_sample_rectagle_viewpager,
),
)

private val callback: (OAuthToken?, Throwable?) -> Unit = { token, error ->
when {
error != null -> {
}

token != null -> {
moveToUserInfoActivity()
}
}
}

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

binding.btnLogin.setOnClickListener {
loginWithKakaoApp()
}
setLoginViewPager()
}

private fun setLoginViewPager() {
loginViewPagerAdapter = LoginViewPagerAdapter(dummyImageList)
binding.run {
vpLogin.adapter = loginViewPagerAdapter
indicatorLoginDots.attachTo(binding.vpLogin)
}
}

private fun loginWithKakaoApp() {
if (UserApiClient.instance.isKakaoTalkLoginAvailable(this)) {
UserApiClient.instance.loginWithKakaoTalk(this) { token, error ->
if (error != null) {
toast("카카오 로그인 실패")
if (error is ClientError && error.reason == ClientErrorCause.Cancelled) {
toast("다시 로그인 해주세요.")
return@loginWithKakaoTalk
}
loginWithKakaoAccount()
} else if (token != null) {
toast("카카오 로그인 성공")
moveToUserInfoActivity()
}
}
} else {
loginWithKakaoAccount()
}
}
Comment on lines +64 to +82
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요기로직은 추후 관심사 분리가 필요하겠죠!?! 한번 확인해주시고 또 다른 예외상황이 있는지도 확인해주세요~!!!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵! 지금 뷰모델 분리하면서 조금 더 세분화 하고 있고, 예외의 경우도 공식문서에서는 유저가 임의로 로그인을 이탈하거나 취소하는 경우만 나와있어서 그 부분만 구현했는데, 또 다른 경우도 고려해보겠습니다!


private fun loginWithKakaoAccount() {
UserApiClient.instance.loginWithKakaoAccount(this, callback = callback)
}

private fun moveToUserInfoActivity() {
startActivity(Intent(this, UserInfoActivity::class.java))
finish()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.hmh.hamyeonham.feature.login

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class LoginViewModel : ViewModel(){

private val _kakaoLoginResult = MutableLiveData<Boolean>()
val kakaoLoginResult: LiveData<Boolean> get() = _kakaoLoginResult
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굿!@!@

Comment on lines +9 to +10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요 값이 왜 있는지 모르겠네욥?!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

뷰모델 분리하기 위해 세팅만 해두고 아직 코드가 완성되지 않아 올리지 못했습니다 ㅎㅎ.. kakaoLoginResult 라이브 데이터의 결과에 따라 로그인 액티비티에서 분기처리 진행할 예정입니다!


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.hmh.hamyeonham.feature.login

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import coil.load
import com.hmh.hamyeonham.feature.login.data.DummyImage
import com.hmh.hamyeonham.feature.login.databinding.ItemLoginViewPagerBinding

class LoginViewPagerAdapter(private val imageList: List<DummyImage>) :
RecyclerView.Adapter<LoginViewPagerAdapter.PagerViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PagerViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_login_view_pager, parent, false)
return PagerViewHolder(ItemLoginViewPagerBinding.bind(view))
}

class PagerViewHolder(private val binding: ItemLoginViewPagerBinding) :
RecyclerView.ViewHolder(binding.root) {

fun onBindView(imageInfo: DummyImage) {
binding.run {
ivLoginViewPagerItem.load(imageInfo.Image) {
placeholder(R.drawable.login_sample_rectagle_viewpager)
error(R.drawable.login_sample_rectagle_viewpager)
}
}
}
}

override fun getItemCount(): Int = imageList.size

override fun onBindViewHolder(holder: PagerViewHolder, position: Int) {
val exploreImage = imageList[position]
holder.onBindView(exploreImage)
}
}
Comment on lines +10 to +38
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요거 리스트 어댑터로 바꿔보시면 좋을 것 같습니다. diffUtil은 ItemDiffCallback 을 사용해주세요~!!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네! 바꾸도록 하겠습니다!

Loading