구글 로그인
구글 로그인과 같은 소셜 로그인 기능을 추가해보자.
Gradle에서 google-service 버전이 4.2.x 버전 이상이어야 한다.
그리고 라이브러리를 설치하자.
그리고 만들어 놓은 구글 로그인 버튼에 id를 추가하자.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LoginActivity">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/signIn_layout"
android:layout_alignParentTop="true"
android:src="@drawable/logo_title"></ImageView>
<LinearLayout
android:id="@+id/signIn_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp">
<EditText
android:id="@+id/email_edit_text"
android:background="@color/colorWhite"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/email"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
>
<EditText
android:inputType="textPassword"
android:id="@+id/password_edit_text"
android:colorControlActivated="@color/colorGoogleSignInPressed"
android:background="@color/colorWhite"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/password"/>
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/email_login_button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="15dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="35dp"
android:text="@string/signin_email"
android:textColor="@color/black"
android:theme="@style/ButtonStyle" />
<android.widget.Button
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="5dp"
android:background="@drawable/btn_signin_facebook"
android:text="@string/signin_facebook"
android:textColor="@color/colorWhite"/>
<android.widget.Button
android:id="@+id/google_signIn_button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="80dp"
android:background="@drawable/btn_signin_google"
android:text="@string/signin_google"
android:textColor="@color/colorWhite"/>
</LinearLayout>
</RelativeLayout>
이제 버튼을 아이디로 찾아 리스너를 달고 동작시켜보자.
package com.example.firstapp
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import com.google.android.gms.auth.api.Auth
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInClient
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.auth.GoogleAuthProvider
class LoginActivity : AppCompatActivity() {
var auth : FirebaseAuth? = null
var googleSignInClient: GoogleSignInClient? = null
var GOOGLE_LOGIN_CODE = 9001
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
auth = FirebaseAuth.getInstance()
//로그인 버튼
var signInButton = findViewById<Button>(R.id.email_login_button)
signInButton.setOnClickListener {
signInAndSingUp()
}
//구글 로그인 버튼
var googleSignInButton = findViewById<Button>(R.id.google_signIn_button)
googleSignInButton.setOnClickListener {
googleLogin()
}
var gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build()
googleSignInClient = GoogleSignIn.getClient(this, gso)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == GOOGLE_LOGIN_CODE){
var result = Auth.GoogleSignInApi.getSignInResultFromIntent(data)
if(result!!.isSuccess){
var account = result.signInAccount
Log.d("account", account.toString())
firebaseAuthWithGoogle(account)
}
}
}
private fun firebaseAuthWithGoogle(account: GoogleSignInAccount?) {
var credential = GoogleAuthProvider.getCredential(account?.idToken,null)
auth?.signInWithCredential(credential)
?.addOnCompleteListener {
task ->
if(task.isSuccessful){
//login success
moveMainPage(task.result?.user)
}else{
//login error
Toast.makeText(this, "signInEmail Error", Toast.LENGTH_SHORT).show()
}
}
}
fun googleLogin(){
var signInIntent = googleSignInClient?.signInIntent
startActivityForResult(signInIntent, GOOGLE_LOGIN_CODE)
}
fun signInAndSingUp(){
val email:String = findViewById<EditText>(R.id.email_edit_text).text.toString()
val password:String = findViewById<EditText>(R.id.password_edit_text).text.toString()
Log.d("email", email)
Log.d("password", password)
auth?.createUserWithEmailAndPassword(email, password)?.addOnCompleteListener {
task ->
if(task.isSuccessful){
//Create a user account
moveMainPage(task.result?.user)
}else if(task.exception?.message.isNullOrEmpty()){
//login error
// Toast.makeText(this, "signInAndSingUp Error", Toast.LENGTH_SHORT).show()
}else{
//login
signInEmail()
}
}
}
fun signInEmail(){
var email:String = findViewById<EditText>(R.id.email_edit_text).text.toString()
var password:String = findViewById<EditText>(R.id.password_edit_text).text.toString()
auth?.signInWithEmailAndPassword(email, password)?.addOnCompleteListener {
task ->
if(task.isSuccessful){
//login success
moveMainPage(task.result?.user)
}else{
//login error
Toast.makeText(this, "signInEmail Error", Toast.LENGTH_SHORT).show()
}
}
}
fun moveMainPage(user: FirebaseUser?){
if(user != null){
startActivity(Intent(this, MainActivity::class.java))
}
}
}
gso는 googleSignIn을 사용하기위한 옵션이라고 생각하면 된다. 옵션을 설정한 뒤 googleSignInClient를 생성하여 띄워준다. 로그인 클라이언트에서 처리한 Intent를 가지고 startActivityForResult를 실행한다.
그럼 LoginActivity에서 Intent를 받아 onActivityResult를 실행하게 된다. onActivityResult를 재정의하여 firebase에 등록하게 만들었다. firebase에 등록하는 것은 일반적인 email을 처리할 때와 동일하다.
또한 SHA1키를 gradle에서 복사하여 firebase 프로젝트에 등록해야 정상적으로 동작한다.
페이스북 로그인
로그인을 하고 프로젝트를 하나 만든다. 그 후 안내에 따라 gradle 설정을 변경한다.
완료했다면 hash key를 받아오자.
fun printHashKey() {
try {
val info = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
for (signature in info.signatures) {
val md: MessageDigest = MessageDigest.getInstance("SHA")
md.update(signature.toByteArray())
val hashKey: String = String(Base64.encode(md.digest(), 0))
Log.i("Hash", "printHashKey() Hash Key: $hashKey")
}
} catch (e: NoSuchAlgorithmException) {
Log.e("Hash", "printHashKey()", e)
} catch (e: Exception) {
Log.e("Hash", "printHashKey()", e)
}
}
위 코드는 hash key를 출력하는 함수이다. 이를 onCreate에 넣어 key를 알아오자.
key를 알아냈다면 단계를 넘어가 등록하면 된다.
등록한 뒤 string에 facebook_app_id, fb_login_protocol_scheme을 변경한다.
그리고 <uses-permission android:name="android.permission.INTERNET"/>라는 권한은 manifest에 등록하자.
마지막으로 meta 데이터 값을 application안에 넣자.
이제 facebook과 firebase 설정만 하면 완료된다. setting에서 uri와 앱 id, 앱 비밀번호를 각각 입력해주면 된다.
facebook로그인 버튼에 아이디를 달고 동작시키자.
<com.facebook.login.widget.LoginButton
android:id="@+id/facebook_signIn_button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="5dp"
android:background="@drawable/btn_signin_facebook"
android:text="@string/signin_facebook"
android:textColor="@color/colorWhite"/>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
//페이스북 로그인 버튼
callbackManager = CallbackManager.Factory.create()
var facebookSignInButton = findViewById<LoginButton>(R.id.facebook_signIn_button)
auth = Firebase.auth
callbackManager = CallbackManager.Factory.create()
facebookSignInButton.setReadPermissions("email", "public_profile")
facebookSignInButton.registerCallback(callbackManager, object : FacebookCallback<LoginResult> {
override fun onSuccess(loginResult: LoginResult) {
Log.d("TAG", "facebook:onSuccess:$loginResult")
handleFacebookAccessToken(loginResult.accessToken)
}
override fun onCancel() {
Log.d("TAG", "facebook:onCancel")
// ...
}
override fun onError(error: FacebookException) {
Log.d("TAG", "facebook:onError", error)
// ...
}
})
}
만들어질 때 facebook Login 버튼에는 직접 Callback을 달 수 있다.
로그인에 성공했다면 handleFacebookAccessToken() 이 실행될 것이다. 여기에 token을 넘겨 로그인을 진행하자.
fun handleFacebookAccessToken(token: AccessToken) {
Log.d("TAG", "handleFacebookAccessToken:$token")
val credential = FacebookAuthProvider.getCredential(token.token)
auth?.signInWithCredential(credential)
?.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
// Sign in success, update UI with the signed-in user's information
Log.d("TAG", "signInWithCredential:success")
val user = auth?.currentUser
moveMainPage(task.result?.user)
} else {
// If sign in fails, display a message to the user.
Log.w("TAG", "signInWithCredential:failure", task.exception)
Toast.makeText(baseContext, "Authentication failed.",
Toast.LENGTH_SHORT).show()
}
}
}
firebase에 등록이 성공했다면 mainpage로 넘어갈 것이다.