Skip to content

Commit

Permalink
Merge pull request #30 from Team-HMH/feat/kakao_login
Browse files Browse the repository at this point in the history
[feat/kakao_login]: 카카오 소셜 로그인, 닉네임 불러오기, 로그아웃 구현
  • Loading branch information
kangyuri1114 authored Jan 4, 2024
2 parents 5a2a84f + 75aa724 commit 8fa5212
Show file tree
Hide file tree
Showing 25 changed files with 451 additions and 15 deletions.
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()
}
}

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

}
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)
}
}
Loading

0 comments on commit 8fa5212

Please sign in to comment.