안드로이드

안드로이드 - 로그인 구현하기

베노 2022. 3. 26. 15:16

최근에 몸이 아프고 기침도 해서 블로그를 잠시 쉬었는데 게임하니깐 멀쩡해진거 같다.

그러니 블로그 다시 시작

 

https://blog.veno.kr/8

 

안드로이드 - 서버연동

안드로이드 앱 제작은 채팅앱 기준으로 작성을 한다. 채팅앱 만들때는 기본적으로 서버가 있어야 하고, 그 서버에서 데이터를 받거나 보내줘서 통신을 한다. 나는 능력이 없어서 서버쪽 개발은

blog.veno.kr

이전 포스팅에 이어서 나갈것이다.

 

물론 내가 블로그를 쉬면서 안드로이드 개발은 그대로 했다. 그래서 내가 진행하고 있는 프로젝트 기준으로 다시 이어 나갈것이지만 아마 진행하는데 큰 차이점은 없을거 같다.

 

저번 포스팅에서는 스플래시를 이용하여 서버점검같은걸 했다. 이 스플레시는 언제든지 변경이 가능하니 본인 입맛대로 골라서 진행하면 될거같다.

 

스플래시가 끝나면 보통 로그인 화면이 나온다.

 

안드로이드는 기본적으로 디자인부분과 코드부분이 나뉜다.

디자인 부분은 우리가 보이는 UI부분이고

코드부분은 UI바탕으로 동작하는 이벤트를 짜주는곳이다.

 


엑티비티 디자인하기


 

이 화면이 디자인부분이다. 우리가 디자인을 한 그대로 안드로이드 앱 화면에 표시된다.

 

<?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"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    <ProgressBar
        android:visibility="gone"
        android:layout_gravity="center"
        android:indeterminateTint="@color/black"
        android:id="@+id/login_progressbar"
        android:layout_width="match_parent"
        android:layout_height="100dp"/>
    </LinearLayout>
    <ImageView
        android:id="@+id/login_image"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:src="@drawable/veno_size_black" />

    <RelativeLayout
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_below="@+id/login_image"
        android:background="@color/background_color">



        <androidx.appcompat.widget.AppCompatEditText
            android:id="@+id/input_email"
            android:layout_width="match_parent"
            android:backgroundTint="@color/black"
            android:layout_height="wrap_content"
            android:textSize="16sp"
            android:textColorLink="@color/black"
            android:textColor="@color/black"
            android:inputType="textEmailAddress"
            android:layout_below="@+id/login_image"
            android:layout_marginTop="40sp"
            android:layout_marginStart="20sp"
            android:layout_marginEnd="20sp"
            android:hint="@string/email"
            tools:ignore="NotSibling" />


        <androidx.appcompat.widget.AppCompatEditText
            android:id="@+id/input_password"
            android:backgroundTint="@color/black"
            android:textSize="16sp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20sp"
            android:layout_marginStart="20sp"
            android:textColor="@color/black"
            android:layout_below="@+id/input_email"
            android:inputType="textPassword"
            android:layout_marginEnd="20sp"
            android:hint="@string/password" />



        <LinearLayout
            android:layout_below="@+id/input_password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/info_text"
            android:layout_marginTop="40sp"
            android:layout_marginStart="20sp"
            android:layout_marginEnd="20sp"
            android:gravity="center"
            android:orientation="horizontal">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="15sp"
                android:textColor="@color/black"
                android:text="@string/is_not_account"/>
            <TextView
                android:id="@+id/loginTosignup_btn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="15sp"
                android:textColor="@color/sky_blue"
                android:layout_marginStart="10sp"
                android:text="@string/signUp"/>
        </LinearLayout>

        <Button
            android:id="@+id/login_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/info_text"
            android:layout_marginStart="20sp"
            android:layout_marginTop="52sp"
            android:layout_marginEnd="20sp"
            android:background="@drawable/button_disign1"
            android:text="@string/login"
            android:textColor="@color/black"
            android:textSize="20sp" />

    </RelativeLayout>

</RelativeLayout>

디자인 부분의 해당 코드이다. 기본적인건 쉬운것이라 넘어가고 생소한것만 설명 해 준다.

 

<ProgressBar
    android:visibility="gone"
    android:layout_gravity="center"
    android:indeterminateTint="@color/black"
    android:id="@+id/login_progressbar"
    android:layout_width="match_parent"
    android:layout_height="100dp"/>

ProgressBar는 로딩바라고 보면 된다. 우리가 게임이나 앱 실행하면 0%~100%로 로딩화면에서 보여주는거다.

안드로이드에서는 동글뱅이로 뱅글뱅글 돌아가는것이 바로 프로그래스이다.

android:visibility="gone"

해당 코드는 프로그래스를 보여줄거냐 안보여줄거냐 이다.

visible과 gone으로 있는데 visible은 보여준다는것이고 gone은 가려준다는것이다.

즉 우리가 로그인 버튼도 안눌렀는데 동글뱅이가 지 혼자서 미친것마냥 뱅글뱅글 돌면 사용자들이 오해 할 수도있으니 일단 안보이게 gone으로 가려주자.

android:indeterminateTint="@color/black"

해당 코드는 동글뱅이의 색상이다. 난 검정색으로 줬다.

프로그래스의 아이디값을 준 이유는 이벤트를 주기 위해 이름을 붙여준거다.

일단 디자인 부분은 이렇게 넘어가주고 그 다음은 이벤트코드로 넘어가주자

 


엑티비티 조작하기


class LoginActivity : AppCompatActivity() {

    var auth : FirebaseAuth? = null


    override fun onCreate(savedInstanceState: Bundle?) {
        auth = FirebaseAuth.getInstance()
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        login_btn.setOnClickListener{ checking_input_empty() }
        loginTosignup_btn.setOnClickListener { startActivity(Intent(this, SignUpActivity::class.java)) }

    }

    fun checking_input_empty(){
        if(input_email.text.toString().isEmpty() || input_password.text.toString().isEmpty()){
            Toast.makeText(this, R.string.empty_Email_and_Password, Toast.LENGTH_SHORT).show()
        } else {
            login_check()
        }
    }
    fun check_email(){
        if(auth?.currentUser?.isEmailVerified == true){
            movepage(auth?.currentUser)
        } else {
            auth!!.currentUser?.sendEmailVerification()?.addOnCompleteListener { email_task ->
                if(email_task.isSuccessful){
                    val alt = AlertDialog.Builder(this)
                    alt.setTitle(R.string.emailVerifiti_title)
                        .setMessage(R.string.emailVerifiti_message)
                        .setPositiveButton(R.string.okay,
                            DialogInterface.OnClickListener { dialog, i ->
                                login_progressbar.visibility = View.GONE
                            })
                    alt.show()
                }
            }
        }
    }
    fun login_check(){
        login_progressbar.visibility = View.VISIBLE
        auth?.signInWithEmailAndPassword(input_email.text.toString(), input_password.text.toString())?.addOnCompleteListener { task ->
           if(task.isSuccessful){
               check_email()
           } else {
               login_progressbar.visibility = View.GONE
               Toast.makeText(this, R.string.not_found_user,Toast.LENGTH_SHORT).show()
           }
        }
    }
    fun movepage(user: FirebaseUser?){
        if(user != null){
            startActivity(Intent(this, MainActivity::class.java))
            finish()
        }
    }

    override fun onStart() {
        super.onStart()
        movepage(auth?.currentUser)
    }
}

꽤 길다. 그래도 난 착한 사람이니 코드 하나씩 해석하는걸 도와주겠다.

var auth : FirebaseAuth? = null

auth라는 이름을 가진 변수를 생성 해 주고 FirebaseAuth라는 인스턴스를 선언 해준다. 

 

login_btn.setOnClickListener{ checking_input_empty() }

 

로그인 디자인부분에 login_btn이라는 이름을 가진 녀석을 불러온다.

setOnClickListener{}는 해당 이름을 가진 녀석을 클릭 했을때 반응 해 주는거다.

나는 여기서 Checking_input_empty라는 함수로 보내주게 했다.

이름에서 알다시피 input부분에 빈값이 있는지 체크해주는 녀석을 깔끔하게 쓰기 위해 따로 함수로 뺴줬다.

fun checking_input_empty(){
    if(input_email.text.toString().isEmpty() || input_password.text.toString().isEmpty()){
        Toast.makeText(this, R.string.empty_Email_and_Password, Toast.LENGTH_SHORT).show()
    } else {
        login_check()
    }
}

코틀린은 함수선언할때 fun쓴 다음 함수 이름을 적으면 된다.

간편하다.

Checking_input_empty는 이름이다.

if(input_email.text.toString().isEmpty() || input_password.text.toString().isEmpty()){

if는 다 알다시피 만약에 라는 뜻으로 조건문이다. 해당 조건이 만족하게 된다면 아래 이벤트를 처리해준다.

나는 여기서 "만약 빈값이 있는지 체크해라"라는 조건을 달았다.

input_email과 input_password라는 입력 가능한 텍스트를 가져와서 빈값인지 아닌지를 체크해야 한다.

코틀린에서는 텍스트를 가져올땐 toString으로 가져와야 한다.

input_email.text.toString()은 input_email에 적은 텍스트값을 가져올때 쓰는것.

여기서 isEmpty라는게 나오는데 이게 코틀린의 매력이다. 자바는 빈값을 체크할때 적는 텍스트가 많다.

하지만 코틀린은 그딴거는 개나줘버리고 간편하게 줄여줬다.

고맙습니다. 젯브레인

그래서 input_email.text.toString().isEmpty는 "디자인부분에서 input_email이라는 이름을 가진 인풋 텍스트값을 가져와서 빈값인지 아닌지 검사해라" 이 뜻이 된다.

또한 중간에 || 이 텍스트가 보인다.

이 텍스트는 조건문에서 조건검사를 할 때 비교연산이다.

비교 연산은 앞부분과 뒷부분을 비교하여 조건을 검사하는거라고 보면 된다. 물론 어떤거냐에 따라 다르다. 하지만 난 지금 적고있는걸 기준으로 간다.

 

if문에서는 여러가지의 비교연산자가 존재한다.

정보처리 자격증을 가진 사람이나 준비중인 사람은 다 알것이다. 

|| 이 녀석은 비교연산자 중에서 "둘중 하나가"(or)라는 뜻이다.

쉽게 비유하는거다. 나중에 비교연산자도 공부해라

 

즉 앞녀석이 빈값이고 뒷녀석이 존재하는값이거나

앞녀석이 존재하는값이고 뒷녀석이 빈값이면 어쨋든 빈값이 하나라도 들어갔기 때문에 메세지를 띄워야 한다.

그러지 않으면 빈값이 있는지 없는지 체크하는 의미가 없는거다.

Toast.makeText(this, R.string.empty_Email_and_Password, Toast.LENGTH_SHORT).show()

Toast는 안드로이드에서 메세지를 띄워주는 녀석이다. 안드로이드에서는 메세지를 띄워주는건 다양하지만 기본중에 기본, 간편하면서 발가락으로 가능한 "토스트메세지" 이다.

여기서 "이메일 및 비밀번호를 적어주세요"라는 메세지가 나온 저 부분이 바로 "토스트메세지"이다.

이거는 너무 간단해서 나중에 똥 쌀때 한번 분석 해 봐라 

똥 다 쌀때까지 분석을 했는데 모르겠으면 댓글이라도 달아주면 나도 똥쌀때 답변 달아주겠다.

 

else {
    login_check()
}

else부분이 나왔다. 이거는 if문 다음으로 나오는 녀석이다.

else는 if문의 조건이 아닐때의 실행하는거다.

세상이 어떻게 똑바로 돌아가겠나 가끔은 한번 삐뚤어져야지

if문도 똑같다. 어떻게 모든 프로그램이 조건을 충족해야 돌아가나, 조건을 충족하지 않고 삐뚤어질때도 있다.

그때 바로 else를 꺼내면 바로 해결된다.

else안에 또 login_check함수가 있다.

 

즉 if문의 "디자인부분에서 input_email이라는 이름을 가진 인풋 텍스트값을 가져와서 빈값인지 아닌지 검사해라"라는 조건이 아니면 else의 login_check부분이 싱행된다.

 

쉽게 이메일이랑 비밀번호값이 정상적으로 들어있다면 else안에 있는 함수가 실행된다.

 

fun login_check(){
    login_progressbar.visibility = View.VISIBLE
    auth?.signInWithEmailAndPassword(input_email.text.toString(), input_password.text.toString())?.addOnCompleteListener { task ->
       if(task.isSuccessful){
           check_email()
       } else {
           login_progressbar.visibility = View.GONE
           Toast.makeText(this, R.string.not_found_user,Toast.LENGTH_SHORT).show()
       }
    }
}

여기서 반가운 녀석이 나왔다. 프로그래스 일단 넌 뒤졌구요

login_progressbar.visibility = View.VISIBLE

login_progressbar라는 이름을 가진 프로그래스를 visible, 보여준다.

이 말은 if문을 잠시 참조한다

이메일과 비밀번호가 빈값이 아니라면 login_check함수로 가서 로딩바를 보여준다.

하지만 언제까지 보여줘야 할까?

 

우리가 로그인을 다 마무리 할때까지이다.

그럼 로그인을 다 마무리할때 어떻게 다시 감추게 해야할까?

 

간단하다. 로그인하는 이벤트가 마무리되면 다시 gone해 주면 된다.

auth?.signInWithEmailAndPassword(input_email.text.toString(), input_password.text.toString())?.addOnCompleteListener { task ->
   if(task.isSuccessful){
       check_email()
   } else {
       login_progressbar.visibility = View.GONE
       Toast.makeText(this, R.string.not_found_user,Toast.LENGTH_SHORT).show()
   }
}

auth는 우리가 처음에 선언했던 변수이다. signInWithEmailAndPassword는 파이어베이스에서 제공해주는 이벤트이다.

우리가 맘대로 못한다. 걍 까라면 까야한다.

저녀석이 서버에 신호를 보내는거다.

signInWithEmailAndPassword를 쓰면 서버한테 "님 저 로그인 시도중인데 로그인좀...."라는거다.

signInWithEmailAndPassword(input_email.text.toString(), input_password.text.toString())

뒤에 input_email과 input_password라는 녀석이 보인다. 맞다 이녀석들이 이메일과 비밀번호이다.

signInWithEmailAndPassword는 sign로그인 with~과(와)함께 Email이메일 Password비밀번호

즉 로그인을 이메일과 비밀번호로 진행한다. 

그러면 이메일과 비밀번호가 있어야 한다.

그래서 input_email이녀석과 input_password 이녀석의 값을 가져오는거고, 맨처음에 빈값인지를 체크를 했던것이다.

addOnCompleteListener이것도 파이어베이스에서 제공해주는거다.

당연히 까라면 까야지

addOnCompleteListener는 파이어베이스에서 제공해준 signInWithEmailAndPassword이녀석의 처리결과를 처리해주는거다.

 

즉 signInWithEmailAndPassword가 정상적으로 처리됬는지 확인해주는게 addOnCompleteListener이 아이다.

그 옆에 task는 task로 념거주는거다

if(task.isSuccessful){
    check_email()
}

만약 넘겨준 task가 isSuccessful(성공적)이면 당연히 아래 함수가 실행된다.

else {
    login_progressbar.visibility = View.GONE
    Toast.makeText(this, R.string.not_found_user,Toast.LENGTH_SHORT).show()
}

else는 if문의 조건이 아니라면 실행한다.

즉 로그인이 정상적으로 처리되지 않는다는것.

여기서 정상적이라는건 등록되어있지 않는 값을 준것이다.

분명 폰에 여자친구 번호가 없는데 부모님이 "여자친구 번호 있냐"라고 물었을때 당연히 나한테는 없는 정보이기에 "아뇨 없습니다."라고 대답해준거라고 보면 된다.

else가 동작되면 그 이후에 처리할 함수가 없다.

함수가 없으니 프로그래스바를 비활성화 해 주면 된다.

login_progressbar.visibility = View.GONE

이렇게 하면 프로그래스바는 로그인을 처리할때까지만 보여주고 처리가 다 끝난거면 감춰주는거다.

 

"어? 근데 코드만 보면 로그인이 실패했을때만 프로그래스바를 안보여준다는건데 만약 성공하게 되면 계속 보여주는거 아닌가?"라고 의문점을 가진다면 당신은 천재이다.

 

 

 

내가 설명을 건너 뛰었기 때문이지

 

어차피 로그인이 되면 바로 화면이 넘거가기 때문에 따로 안가려줘도 된다. 로그인 한 후 넘어가게 되는 화면에는 당연히 프로그래스바가 없으니 사용자들한테는 안보여지게 된다

 

최종적으로 로그인화면에서의 프로그래스바의 역할은 아래와 같다.

 

프로그래스바는 우리가 로그인을 시도할때, 기다려달라는 뜻의 프로그래스바로 로그인의 성공의 유/무를 따져 보여주고 가려줘야 한다.

만약 로그인이 성공하게 되면 다음 화면으로 넘어가는데, 넘어가는 화면에서는 어차피 프로그래스바가 없으니 성공했을때 따로 안가려줘도 화면이 바뀌면서 알아서 가려지니 안적어도 되고,

만약 로그인이 실패하게 되면 코드로 프로그래스바를 가려주고 실패를 했다는 메세지를 보여주면 된다.

이렇게 프로그래스바를 처리하면 된다.

 

위에서 설명했던 

if(task.isSuccessful){
    check_email()
}

이 코드가 로그인이 성공했을때 부분이다.

여기서 cehck_email이라는 함수로 또 넘겨줬다.

fun check_email(){
    if(auth?.currentUser?.isEmailVerified == true){
        movepage(auth?.currentUser)
    } else {
        auth!!.currentUser?.sendEmailVerification()?.addOnCompleteListener { email_task ->
            if(email_task.isSuccessful){
                val alt = AlertDialog.Builder(this)
                alt.setTitle(R.string.emailVerifiti_title)
                    .setMessage(R.string.emailVerifiti_message)
                    .setPositiveButton(R.string.okay,
                        DialogInterface.OnClickListener { dialog, i ->
                            login_progressbar.visibility = View.GONE
                        })
                alt.show()
            }
        }
    }
}

이거는 추가해도 되고 안해도 된다.

나는 엉뚱한 이메일을 넣는 사람들이 있을까봐 집어넣은거다. 위 함수는 "입력한 이메일이 진짜로 존재하는 이메일인가"를 구별해주는 함수이다.

 

여기서

auth?.currentUser

라는게 나온다. 이것도 파이어베이스에서 제공해주는걸로 위 아기자기한 짧은 코드는 해당 유저가 로그인했을때만 유효하는 코드이다.

 

보통 로그인한 유저의 정보를 가져올때 쓴다.

어떤 정보든.

그래서 진짜 존재하는 이메일인지 판단하기 위해 먼저 이메일을 가져와야 한다.

하지만 어떻게?

그래서 필요한게 auth?.currentUser라는 값이다.

지금 로그인한 내 정보에 있는 이메일을 가져오기 위해

if(auth?.currentUser?.isEmailVerified == true){
    movepage(auth?.currentUser)
}

isEmailVerified는 이메일이 인증된 이메일인지 체크해주는거다. 

이상하게도 이거는 로그인이 된 상태여야 확인이 가능하다. 그래서 코드를 짤때 로그인을 먼저 진행시킨 다음 이메일이 인증된건지 체크가 가능하기 때문이다.

isEmailVerified은 true와 false값만 보내준다.

당연히 true이면 이메일이 인증된 유저, false이면 이메일이 인증안된 유저

코드는 "만약 이메일이 인증된 유저이면" 아래 movepage(auth?.currentUser)라는 함수로 보내준다.

당연히 인증이 안되면 인증을 시켜줘야 한다.

 

else {
    auth!!.currentUser?.sendEmailVerification()?.addOnCompleteListener { email_task ->
        if(email_task.isSuccessful){
            val alt = AlertDialog.Builder(this)
            alt.setTitle(R.string.emailVerifiti_title)
                .setMessage(R.string.emailVerifiti_message)
                .setPositiveButton(R.string.okay,
                    DialogInterface.OnClickListener { dialog, i ->
                        login_progressbar.visibility = View.GONE
                    })
            alt.show()
        }
    }
}

sendEmailVerification은 로그인한 유저의 이메일로 인증메일을 전송시킨다. 이것도 전송이 정상적으로 됬는지 체크해야 하나보다. addOnCompleteListener로 처리해주자.

 

email_task로 감지 시켜주자

 if(email_task.isSuccessful){
                    val alt = AlertDialog.Builder(this)
                    alt.setTitle(R.string.emailVerifiti_title)
                        .setMessage(R.string.emailVerifiti_message)
                        .setPositiveButton(R.string.okay,
                            DialogInterface.OnClickListener { dialog, i ->
                                login_progressbar.visibility = View.GONE
                            })
                    alt.show()
                }

만약 이메일전송이(email_task) 성공적으로(isSuccessful)보냈다면

다이얼로그로 보여준다. 

어떤걸 보여주냐

그냥 인증메일을 보냈다. 이메일을 확인 해 봐라 이거다.

 

이메일을 확인하면 링크가 포함된 인증메일이 도착되어있다. 링크를 누르면 

isEmailVerified이 true가 된다.

 

그럼 

if(auth?.currentUser?.isEmailVerified == true){
    movepage(auth?.currentUser)
}

이 부분이 먹히게 된다.

 

이제 movepage부분 함수를 보자

fun movepage(user: FirebaseUser?){
    if(user != null){
        startActivity(Intent(this, MainActivity::class.java))
        finish()
    }
}

movepage()라는 함수는 알겠는데 괄호안에 user: FirebaseUser는 무엇일까

괄호안에 들어가는건 흔히 파라미터라고 불린다

파라미터는 함수에 전달된 값을 받기 위해 만든 변수이다.

그래서 movepage에 use라는 변수를 만들고 user라는변수에 FirebaseUser라는걸 받는다

FirebaseUser는 로그인한 사용자를 가져오는거다.

if문의 user(FirebaseUser로 지정된 변수)값이 null이 아니면 아래 함수가 실행된다.

 

startActivity(Intent(this, MainActivity::class.java))
            finish()

이거는 엑티비티 실행한다는거다.

그냥 화면을 바꿔서 MainActivity라는 이름을 가진 코틀린 파일을 호출하고 finish로 로그인 엑티비티는 끝내준다.

보통 finish를 안적어주면 화면에 누적이 되어서 뒤로가기 버튼을 누르면 우리가 봤던 화면들이 계속 나온다.

그래서 finish를 써줘야 한다.

 

override fun onStart() {
    super.onStart()
    movepage(auth?.currentUser)
}

onStart는 안드로이드의 엑티비티의 생명주기이다.

여기서 생명주기란?

안드로이드는 우리가 보여주는 화면(엑티비티)에 대해 여러가지의 옵션을 제공해준다.

예를 들면 로그인화면을 보고있는데 다른 화면이 나오거나, 화면이 보여주기직전에 또 다른 이벤트를 처리할건지 등 화면에 옵션을 걸어 작업을 처리할 수 있다.

이런거를 통틀어서 "생명주기"이다.

안드로이드에서는 생명주기에 대한 여러가지의 함수가 존재한다.

생명주기는 순서대로 동작하니 외우거나 따로 적어야 한다.

 

동작순서는 다음과 같다.

onCreate : 시스템이 활동을 생성할 때 실행되는것이다. 무조건 필수적으로 구현해야 하는것이다. 디자인화면을 보여줄때 보통 이 함수에 지정된다. 해당 함수가 정상작동하면 onStart가 실행된다.

onStart : 엑티비티가 사용자에게 바로 보여주기 직전에 호출된다.

onResume : 해당 엑티비티에 상호작용하기 직전에 호출한다.

onPause : 엑티비티에 다른 엑티비티가 보여주어서 해당 엑티비티가 멈췄을때 호출한다.

onStop : 해당 엑티비티가 우리에게 더 이상 안보여줄때 호출한다.

onDestroy : 해당 엑티비티가 사라졌을때의 호출된다. 이거는 프로세스가 종료되었을때 반응된다.

 

onDestroy와 finish는 다르다. finish는 단순 화면을 없애주는거지만, onDestroy는 프로세스가 완전히 종료될때, 즉 앱을 강제종료 했을때의 반응하는거 같다. 

 

이거는 안드로이드 공식문서를 읽으면 좋을거 같다.

 

이렇게 하면 onStart, 즉 로그인 화면이 우리에게 보여주기 직전에 로그인 한 유저인지 체크 한 다음 로그인한 유저면 화면을 바로 MainActivity로 이동시켜주고 아니라면 무시하게 된다.

 

 


끝으로


최근에 몸살에 감기에 온몸 여러곳이 아파서 잠시 쉬었다. 물론 코딩하는것도 오랜만에 하는거라 다 까먹은거 같다.

공부 못하는 나의 단점이다.

코딩할때 안드로이드로 잡은것도 후회한다. 매번 구글 i/o를 봐야해서 바뀐점을 꼭 숙지해야 하고 좀 어렵기도 하다.

그래도 처음으로 시작한건데 포기하기에는 너무 늦었다. 이 포스팅을 보고 "나도 코딩은 안드로이드!!"하는 사람이 있다면 뺨 싸대기를 때려서 정신차리게 해 주고 싶다.

 

다음은 회원가입을 통해 사용자들이 적은 정보를 바탕으로 데이터베이스에 저장 시키고 회원가입이나 로그인할때 필요한 정보를 구현 할 예정이다.

만약 포스팅에 문제가 있거나 이해가 안가는 부분이 있음 댓글이나 나한테 카톡 보내주면 된다.

물론 내 카톡은 알아서 찾아내길

 

그리고 포스팅이 늦어도 넓은 아량으로 이해 해 주길 바란다.

왜냐하면

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

솔직히 게임은 못참지ㅋㅋ