diff --git a/android/HowAboutTrip/app/build.gradle.kts b/android/HowAboutTrip/app/build.gradle.kts index 608cad56..6205d766 100644 --- a/android/HowAboutTrip/app/build.gradle.kts +++ b/android/HowAboutTrip/app/build.gradle.kts @@ -1,6 +1,9 @@ +import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties + plugins { id("com.android.application") id("org.jetbrains.kotlin.android") + id("com.google.gms.google-services") id("kotlin-kapt") } @@ -21,6 +24,10 @@ android { } testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + buildConfigField("String", "GOOGLE_OAUTH_ID", getApiKey("google_oauth_id")) + buildConfigField("String", "GOOGLE_MAP_API_KEY", getApiKey("google_map_api_key")) + buildConfigField("String", "GOOGLE_SERVER_ID", getApiKey("google_server_id")) } buildTypes { @@ -41,6 +48,8 @@ android { } } +fun getApiKey(propertyKey: String):String = gradleLocalProperties(rootDir).getProperty(propertyKey) + dependencies { implementation("androidx.core:core-ktx:1.12.0") @@ -48,6 +57,17 @@ dependencies { implementation("com.google.android.material:material:1.11.0") implementation("androidx.constraintlayout:constraintlayout:2.1.4") implementation("com.airbnb.android:lottie:6.3.0") + + implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.2") + implementation("androidx.fragment:fragment-ktx:1.7.0-alpha07") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2") + + implementation(platform("com.google.firebase:firebase-bom:32.7.0")) + implementation("com.google.firebase:firebase-analytics") + implementation("com.google.firebase:firebase-auth:22.3.0") + implementation("com.google.android.gms:play-services-auth:20.7.0") + + testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") diff --git a/android/HowAboutTrip/app/google-services.json b/android/HowAboutTrip/app/google-services.json new file mode 100644 index 00000000..1d353f25 --- /dev/null +++ b/android/HowAboutTrip/app/google-services.json @@ -0,0 +1,47 @@ +{ + "project_info": { + "project_number": "740845966307", + "project_id": "howabouttrip", + "storage_bucket": "howabouttrip.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:740845966307:android:71aff1bfe733b688ad46d6", + "android_client_info": { + "package_name": "com.project.how" + } + }, + "oauth_client": [ + { + "client_id": "740845966307-oulmuvm5mv595vlu9hf1a3j5n4ouvskg.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.project.how", + "certificate_hash": "8f29dbe96504294182411cc8b5af35fee8e57de8" + } + }, + { + "client_id": "740845966307-vhqequ0l999eglm9p87su14da4bjreid.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDg0_7_UQD4gNj9XmKnQZpBGREl0r9CZ_Q" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "740845966307-vhqequ0l999eglm9p87su14da4bjreid.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/HowAboutTrip/app/src/main/AndroidManifest.xml b/android/HowAboutTrip/app/src/main/AndroidManifest.xml index 5e805307..67856c38 100644 --- a/android/HowAboutTrip/app/src/main/AndroidManifest.xml +++ b/android/HowAboutTrip/app/src/main/AndroidManifest.xml @@ -2,6 +2,7 @@ + + - + \ No newline at end of file diff --git a/android/HowAboutTrip/app/src/main/java/com/project/how/model/LoginRepository.kt b/android/HowAboutTrip/app/src/main/java/com/project/how/model/LoginRepository.kt new file mode 100644 index 00000000..40d3617f --- /dev/null +++ b/android/HowAboutTrip/app/src/main/java/com/project/how/model/LoginRepository.kt @@ -0,0 +1,26 @@ +package com.project.how.model + +import android.util.Log +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.google.firebase.auth.FirebaseAuth +import com.google.firebase.auth.FirebaseUser +import com.google.firebase.auth.GoogleAuthProvider + +class LoginRepository { + private val firebaseAuth = FirebaseAuth.getInstance() + private val _userLiveData = MutableLiveData() + val userLiveData: LiveData + get() = _userLiveData + + fun getUser(idToken: String) { + val credential = GoogleAuthProvider.getCredential(idToken, null) + firebaseAuth.signInWithCredential(credential).addOnCompleteListener{ + if(it.isSuccessful){ + _userLiveData.postValue(firebaseAuth.currentUser) + } else{ + Log.e("GoogleAuthRepository", "getUser is failed\n${it.exception}") + } + } + } +} \ No newline at end of file diff --git a/android/HowAboutTrip/app/src/main/java/com/project/how/view/activity/LoginActivity.kt b/android/HowAboutTrip/app/src/main/java/com/project/how/view/activity/LoginActivity.kt index 45aac251..354a3599 100644 --- a/android/HowAboutTrip/app/src/main/java/com/project/how/view/activity/LoginActivity.kt +++ b/android/HowAboutTrip/app/src/main/java/com/project/how/view/activity/LoginActivity.kt @@ -1,12 +1,58 @@ package com.project.how.view.activity +import android.app.Activity +import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.util.Log +import android.widget.Toast +import androidx.activity.result.ActivityResult +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.viewModels +import androidx.databinding.DataBindingUtil +import com.google.android.gms.auth.api.identity.BeginSignInRequest +import com.google.android.gms.auth.api.signin.GoogleSignIn +import com.google.android.gms.auth.api.signin.GoogleSignInClient +import com.google.android.gms.auth.api.signin.GoogleSignInOptions +import com.google.android.gms.common.api.ApiException +import com.project.how.BuildConfig import com.project.how.R +import com.project.how.databinding.ActivityLoginBinding +import com.project.how.view_model.LoginViewModel class LoginActivity : AppCompatActivity() { + private lateinit var binding : ActivityLoginBinding + private val viewModel: LoginViewModel by viewModels() + private lateinit var activityResultLauncher : ActivityResultLauncher + private lateinit var googleSignInRequest: GoogleSignInClient + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_login) + binding = DataBindingUtil.setContentView(this, R.layout.activity_login) + binding.login = this + val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestIdToken(BuildConfig.GOOGLE_SERVER_ID) + .requestEmail() + .build() + googleSignInRequest = GoogleSignIn.getClient(this, gso) + activityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ + if(it.resultCode == Activity.RESULT_OK) { + val task = GoogleSignIn.getSignedInAccountFromIntent(it.data) + try { + val account = task.result + viewModel.getUser(account.idToken!!) + Log.d("activityResultLauncher", "Login Success\nidToken : ${account.idToken}\nid : ${account.id}\nemail : ${account.email}") + startActivity(Intent(this, MainActivity::class.java)) + } catch (e: Exception){ + Log.e("activityResultLauncher", "Login Failed\nError : ${e.stackTrace}\n${e.message}") + } + } + } + + binding.googleLogin.setOnClickListener { + activityResultLauncher.launch(googleSignInRequest.signInIntent) + binding.lottie.pauseAnimation() + } } } \ No newline at end of file diff --git a/android/HowAboutTrip/app/src/main/java/com/project/how/view/activity/MainActivity.kt b/android/HowAboutTrip/app/src/main/java/com/project/how/view/activity/MainActivity.kt new file mode 100644 index 00000000..ad1649f3 --- /dev/null +++ b/android/HowAboutTrip/app/src/main/java/com/project/how/view/activity/MainActivity.kt @@ -0,0 +1,16 @@ +package com.project.how.view.activity + +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import androidx.databinding.DataBindingUtil +import com.project.how.R +import com.project.how.databinding.ActivityMainBinding + +class MainActivity : AppCompatActivity() { + private lateinit var binding: ActivityMainBinding + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding= DataBindingUtil.setContentView(this, R.layout.activity_main) + + } +} \ No newline at end of file diff --git a/android/HowAboutTrip/app/src/main/java/com/project/how/view/activity/SplashActivity.kt b/android/HowAboutTrip/app/src/main/java/com/project/how/view/activity/SplashActivity.kt index 5b4c2650..91971ab6 100644 --- a/android/HowAboutTrip/app/src/main/java/com/project/how/view/activity/SplashActivity.kt +++ b/android/HowAboutTrip/app/src/main/java/com/project/how/view/activity/SplashActivity.kt @@ -1,12 +1,25 @@ package com.project.how.view.activity +import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import androidx.databinding.DataBindingUtil +import androidx.lifecycle.lifecycleScope import com.project.how.R +import com.project.how.databinding.ActivitySplashBinding +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch class SplashActivity : AppCompatActivity() { + private lateinit var binding : ActivitySplashBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_splash) + binding = DataBindingUtil.setContentView(this, R.layout.activity_splash) + binding.splash = this + + lifecycleScope.launch { + delay(1000) + startActivity(Intent(this@SplashActivity, LoginActivity::class.java)) + } } } \ No newline at end of file diff --git a/android/HowAboutTrip/app/src/main/java/com/project/how/view_model/LoginViewModel.kt b/android/HowAboutTrip/app/src/main/java/com/project/how/view_model/LoginViewModel.kt new file mode 100644 index 00000000..c18e0a5e --- /dev/null +++ b/android/HowAboutTrip/app/src/main/java/com/project/how/view_model/LoginViewModel.kt @@ -0,0 +1,17 @@ +package com.project.how.view_model + +import androidx.lifecycle.LiveData +import androidx.lifecycle.ViewModel +import com.google.firebase.auth.FirebaseUser +import com.project.how.model.LoginRepository + +class LoginViewModel : ViewModel() { + private var loginRepository : LoginRepository = LoginRepository() + private val _userLiveData = loginRepository.userLiveData + val userLiveData: LiveData + get() = _userLiveData + + fun getUser(idToken: String){ + loginRepository.getUser(idToken) + } +} \ No newline at end of file diff --git a/android/HowAboutTrip/app/src/main/res/drawable/google_login.png b/android/HowAboutTrip/app/src/main/res/drawable/google_login.png new file mode 100644 index 00000000..27e88b87 Binary files /dev/null and b/android/HowAboutTrip/app/src/main/res/drawable/google_login.png differ diff --git a/android/HowAboutTrip/app/src/main/res/drawable/logo.png b/android/HowAboutTrip/app/src/main/res/drawable/logo.png new file mode 100644 index 00000000..62d14b26 Binary files /dev/null and b/android/HowAboutTrip/app/src/main/res/drawable/logo.png differ diff --git a/android/HowAboutTrip/app/src/main/res/font/blinker_semibold.ttf b/android/HowAboutTrip/app/src/main/res/font/blinker_semibold.ttf new file mode 100644 index 00000000..408a9cf0 Binary files /dev/null and b/android/HowAboutTrip/app/src/main/res/font/blinker_semibold.ttf differ diff --git a/android/HowAboutTrip/app/src/main/res/layout/activity_login.xml b/android/HowAboutTrip/app/src/main/res/layout/activity_login.xml index 2f58c5f8..835729db 100644 --- a/android/HowAboutTrip/app/src/main/res/layout/activity_login.xml +++ b/android/HowAboutTrip/app/src/main/res/layout/activity_login.xml @@ -15,25 +15,46 @@ + + \ No newline at end of file diff --git a/android/HowAboutTrip/app/src/main/res/layout/activity_main.xml b/android/HowAboutTrip/app/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000..2832d141 --- /dev/null +++ b/android/HowAboutTrip/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/HowAboutTrip/app/src/main/res/layout/activity_splash.xml b/android/HowAboutTrip/app/src/main/res/layout/activity_splash.xml index 45bd0a1a..d6b7f38c 100644 --- a/android/HowAboutTrip/app/src/main/res/layout/activity_splash.xml +++ b/android/HowAboutTrip/app/src/main/res/layout/activity_splash.xml @@ -1,9 +1,42 @@ - + xmlns:tools="http://schemas.android.com/tools"> - \ No newline at end of file + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/HowAboutTrip/app/src/main/res/values/colors.xml b/android/HowAboutTrip/app/src/main/res/values/colors.xml index 2ee496c4..d2a60bbd 100644 --- a/android/HowAboutTrip/app/src/main/res/values/colors.xml +++ b/android/HowAboutTrip/app/src/main/res/values/colors.xml @@ -3,4 +3,5 @@ #FF000000 #FFFFFFFF #FFD9D9D9 + #FFCF2727 \ No newline at end of file diff --git a/android/HowAboutTrip/app/src/main/res/values/strings.xml b/android/HowAboutTrip/app/src/main/res/values/strings.xml index cb39c3cb..1eb546af 100644 --- a/android/HowAboutTrip/app/src/main/res/values/strings.xml +++ b/android/HowAboutTrip/app/src/main/res/values/strings.xml @@ -1,3 +1,6 @@ HowAboutTrip + HowAboutTrip에서\n여행 계획을 세우는 건 어떤가요? + google login + How About Trip \ No newline at end of file diff --git a/android/HowAboutTrip/build.gradle.kts b/android/HowAboutTrip/build.gradle.kts index d28e7454..591e568c 100644 --- a/android/HowAboutTrip/build.gradle.kts +++ b/android/HowAboutTrip/build.gradle.kts @@ -1,6 +1,12 @@ +buildscript { + dependencies { + classpath("com.google.gms:google-services:4.4.0") + } +} // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { id("com.android.application") version "8.2.1" apply false id("org.jetbrains.kotlin.android") version "1.9.10" apply false + id("com.google.gms.google-services") version "4.4.0" apply false kotlin("kapt") version "1.9.22" } \ No newline at end of file