Android

ํšŒ์›๊ฐ€์ž…, ๋กœ๊ทธ์ธ, ๋กœ๊ทธ์•„์›ƒ ๊ธฐ๋Šฅ ์•ฑ(app)์„ Retrofit2 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋งŒ๋“ค๊ธฐ

567Rabbit 2024. 6. 13. 15:47

 

Restful API(๋ฉ”๋ชจ API)๋ฅผ ๋งŒ๋“ค๊ณ , MySQL๊ณผ ์—ฐ๋™ํ•˜์—ฌ Postman์œผ๋กœ ๊ฐœ๋ฐœํ•œ ํ›„, ์ง„ํ–‰ํ•˜์˜€๋‹ค.

 

 

 

 

 

์•กํ‹ฐ๋น„ํ‹ฐ ์„ธ ๊ฐœ ๋งŒ๋“ค๊ธฐ

 

 

 


ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ •ํ•˜๊ธฐ

 



 

 

Retrofit ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ํ•˜๊ธฐ

 

build.gradle.kts(:app)์—์„œ

implementation("com.squareup.retrofit2:retrofit:2.11.0")
implementation("com.squareup.retrofit2:converter-gson:2.11.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")

 

 

ํ•˜๊ณ , Sync ๋ˆŒ๋Ÿฌ์ค€๋‹ค.

 

 

 

 

 

activity_login.xml ๋งŒ๋“ค๊ธฐ

 

 

๊ธ€์ž์— ๋ฐ‘์ค„ ์ƒ๊ธฐ๊ฒŒ ํ•˜๊ธฐ

 

 

 

 

 

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".LoginActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="10dp"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="10dp"
        android:layout_marginBottom="10dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:layout_marginBottom="30dp"
            android:gravity="center"
            android:text="๋กœ๊ทธ์ธ"
            android:textSize="32sp" />

        <EditText
            android:id="@+id/editEmail"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:ems="10"
            android:hint="์ด๋ฉ”์ผ ์ž…๋ ฅ..."
            android:inputType="textEmailAddress"
            android:textSize="20sp" />

        <EditText
            android:id="@+id/editPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="50dp"
            android:ems="10"
            android:hint="๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ..."
            android:inputType="textPassword"
            android:textSize="20sp" />

        <Button
            android:id="@+id/btnLogin"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="30dp"
            android:text="๋กœ๊ทธ์ธ"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/txtRegister"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@string/txt_register"
            android:textColor="#3F51B5"
            android:textSize="20sp" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

 

 

LoginActivity.java

 

ํ™”๋ฉด์—ฐ๊ฒฐ ์ž๋ฐ”์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ 

 

package com.~.memo;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

public class LoginActivity extends AppCompatActivity {

    EditText editEmail;
    EditText editPassword;
    TextView txtRegister;
    Button btnLogin;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        editEmail = findViewById(R.id.editEmail);
        editPassword = findViewById(R.id.editPassword);
        txtRegister = findViewById(R.id.txtRegister);
        btnLogin = findViewById(R.id.btnLogin);

        txtRegister.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //ํšŒ์›๊ฐ€์ž… ์•กํ‹ฐ๋น„ํ‹ฐ ์‹คํ–‰
                Intent intent = new Intent(LoginActivity.this, RegisterActivity.class);
                startActivity(intent);
                finish();
            }
        });
        
    }
}

 

 

 

 

activity_Register.xml ๋งŒ๋“ค๊ธฐ

 

 

 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".LoginActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="10dp"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="10dp"
        android:layout_marginBottom="10dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:layout_marginBottom="30dp"
            android:gravity="center"
            android:text="ํšŒ์›๊ฐ€์ž…"
            android:textSize="32sp" />

        <EditText
            android:id="@+id/editEmail"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:ems="10"
            android:hint="์ด๋ฉ”์ผ ์ž…๋ ฅ..."
            android:inputType="textEmailAddress"
            android:textSize="20sp" />

        <EditText
            android:id="@+id/editPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:ems="10"
            android:hint="๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ..."
            android:inputType="textPassword"
            android:textSize="20sp" />

        <EditText
            android:id="@+id/editNickname"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="50dp"
            android:ems="10"
            android:hint="๋‹‰๋„ค์ž„ ์ž…๋ ฅ..."
            android:inputType="text"
            android:textSize="20sp" />

        <Button
            android:id="@+id/btnRegister"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="30dp"
            android:text="ํšŒ์›๊ฐ€์ž…"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/txtLogin"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@string/txt_login"
            android:textColor="#3F51B5"
            android:textSize="20sp" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

 

 

RegisterActivity.java

 

ํ™”๋ฉด์—ฐ๊ฒฐ ์ž๋ฐ”์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ 

package com.~.memo;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;


public class RegisterActivity extends AppCompatActivity {
    
    EditText editEmail;
    EditText editPassword;
    EditText editNickname;
    Button btnRegister;
    TextView txtLogin;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);
        
        editEmail = findViewById(R.id.editEmail);
        editPassword = findViewById(R.id.editPassword);
        editNickname = findViewById(R.id.editNickname);
        btnRegister = findViewById(R.id.btnRegister);
        txtLogin = findViewById(R.id.txtLogin);
        
        txtLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // ๋กœ๊ทธ์ธ ์•กํ‹ฐ๋น„ํ‹ฐ ์‹คํ–‰
                Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
                startActivity(intent);
                finish();
            }
        });
        
    }

}

 

 

 

 

 

api, config ๋งŒ๋“ค๊ธฐ

 

 

 

 

NetworkClient.java

package com.~.memo.api;

import android.content.Context;

import com.~.memo.config.Config;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class NetworkClient {

    public static Retrofit retrofit;

    public static Retrofit getRetrofitClient(Context context){
        if(retrofit == null){
            // ํ†ต์‹  ๋กœ๊ทธ ํ™•์ธํ• ๋•Œ ํ•„์š”ํ•œ ์ฝ”๋“œ
            HttpLoggingInterceptor loggingInterceptor =
                    new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

            // ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ๊ด€๋ จ ์ฝ”๋“œ
            OkHttpClient httpClient = new OkHttpClient.Builder()
                    .connectTimeout(1, TimeUnit.MINUTES)
                    .readTimeout(1, TimeUnit.MINUTES)
                    .writeTimeout(1, TimeUnit.MINUTES)
                    .addInterceptor(loggingInterceptor)
                    .build();
            // ๋„คํŠธ์›Œํฌ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๊ณ  ๋ฐ›๋Š”
            // ๋ ˆํŠธ๋กœํ• ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ด€๋ จ ์ฝ”๋“œ
            retrofit = new Retrofit.Builder()
                    .baseUrl(Config.DOMAIN)
                    .client(httpClient)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

 

 

 

UserApi.java

package com.~.memo.api;

import com.~.memo.model.User;
import com.~.memo.model.UserRes;

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.POST;

public interface UserApi {  //์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค.

    // HTTP Method ์จ์ฃผ๊ณ , ๊ทธ ์•ˆ์—๋Š” ๊ฒฝ๋กœ๋ฅผ ์จ์ค€๋‹ค.
    // ํ•จ์ˆ˜์˜ ๋ฆฌํ„ด ๋ฐ์ดํ„ฐ ํƒ€์ž…์€, Call ์•ˆ์— ์‘๋‹ต์œผ๋กœ ๋ฐ›์„ ํด๋ž˜์Šค๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.
    // ํ•จ์ˆ˜๋ช…์„ ์ž‘์„ฑํ•ด์ฃผ๊ณ , ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ž‘์„ฑ, ๋ฐ›์„ ๋ฐ์ดํ„ฐ๋Š” ๋ฆฌํ„ด์— ์ž‘์„ฑ.
    
    // ํšŒ์›๊ฐ€์ž… API
    @POST("/dev/user/register")
    Call<UserRes> register(@Body User user);

    // ๋กœ๊ทธ์ธ API
    @POST("/dev/user/login")
    Call<UserRes> login(@Body User user);
    
}

 

 

 

Config.java

package com.yujinoh.memo.config;

public class Config {
    public static final String YOUTUBE_KEY = "์ž์‹ ์˜ key ์ž…๋ ฅ";
    public static final String DOMAIN = "์ž์‹ ์˜ ์•„๋งˆ์กด api ์ฃผ์†Œ ์ž…๋ ฅ";
    
    //public static final String DOMAIN = "https://vrskmc6b8c.execute-api.ap-northeast-2.amazonaws.com";

}

 

 

 

 

 

model ํŒจํ‚ค์ง€ ๋งŒ๋“ค๊ณ , User ์™€ UserRes ํด๋ž˜์Šค ๋งŒ๋“ค๊ธฐ

 

User ํด๋ž˜์Šค ๋งŒ๋“ค๊ธฐ

package com.~.memo.model;

public class User {

    public String email;
    public String password;
    public String nickname;

    public User(){

    }

    public User(String email, String password){
        this.email = email;
        this.password = password;
    }

    public User(String email, String password, String nickname) {
        this.email = email;
        this.password = password;
        this.nickname = nickname;
    }
}

 

 

 

UserRes ํด๋ž˜์Šค

package com.~.memo.model;

public class UserRes {

    public String result;
    public String accessToken;
}

 

 

 

 

 

 

RegisterActivity.java

 

ํšŒ์›๊ฐ€์ž… ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋ฉด, ํšŒ์›๊ฐ€์ž… ๋˜๋„๋ก postman๊ณผ ์—ฐ๊ฒฐํ•˜๊ธฐ

 

package com.~.memo;

import android.app.Dialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.util.Patterns;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.google.android.material.snackbar.Snackbar;
import com.~.memo.api.NetworkClient;
import com.~.memo.api.UserApi;
import com.~.memo.config.Config;
import com.~.memo.model.User;
import com.~.memo.model.UserRes;

import java.util.regex.Pattern;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;


public class RegisterActivity extends AppCompatActivity {

    EditText editEmail;
    EditText editPassword;
    EditText editNickname;
    Button btnRegister;
    TextView txtLogin;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);

        editEmail = findViewById(R.id.editEmail);
        editPassword = findViewById(R.id.editPassword);
        editNickname = findViewById(R.id.editNickname);
        btnRegister = findViewById(R.id.btnRegister);
        txtLogin = findViewById(R.id.txtLogin);

        txtLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // ๋กœ๊ทธ์ธ ์•กํ‹ฐ๋น„ํ‹ฐ ์‹คํ–‰
                Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
                startActivity(intent);
                finish();
            }
        });

        btnRegister.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 1. ์œ ์ €๊ฐ€ ์ž…๋ ฅํ•œ ๋ฐ์ดํ„ฐ๋“ค์„ ๊ฐ€์ ธ์˜จ๋‹ค.
                String email = editEmail.getText().toString().trim();
                String password = editPassword.getText().toString().trim();
                String nickname = editNickname.getText().toString().trim();

                if(email.isEmpty() || password.isEmpty() || nickname.isEmpty()){
                    Snackbar.make(btnRegister, "ํ•„์ˆ˜ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค. ๋ชจ๋‘์ž…๋ ฅํ•˜์„ธ์š”.", Snackbar.LENGTH_SHORT).show();
                    return;
                }
                // 2. ์ด๋ฉ”์ผ ํ˜•์‹์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ์ฒดํฌ
                // ์ž๋ฐ”์˜ ์ด๋ฉ”์ผ ํ˜•์‹ ์ฒดํฌํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ Pattern
                Pattern pattern = Patterns.EMAIL_ADDRESS;
                if(pattern.matcher(email).matches() == false){
                    Snackbar.make(btnRegister,"์ด๋ฉ”์ผ ํ˜•์‹์„ ๋ฐ”๋ฅด๊ฒŒ ์ž‘์„ฑํ•˜์„ธ์š”.",Snackbar.LENGTH_SHORT).show();
                    return;
                }

                // ํšŒ์›๊ฐ€์ž… API๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

                // 0. ๋‹ค์ด์–ผ๋กœ๊ทธ๋ฅผ ๋ณด์—ฌ์ค€๋‹ค.
                showProgress();

                // 1. ๋ ˆํŠธ๋กœํ• ๋ณ€์ˆ˜ ์ƒ์„ฑ : api ํŒจํ‚ค์ง€์— NetworkClient.java ํŒŒ์ผ์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.
                Retrofit retrofit = NetworkClient.getRetrofitClient(RegisterActivity.this);

                // 2. api ํŒจํ‚ค์ง€์— ์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ฐ์ฒด๋กœ ์ƒ์„ฑ : api ํŒจํ‚ค์ง€์— ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
                UserApi api = retrofit.create(UserApi.class);

                // 3. ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ ๋‹ค.
                User user = new User(email, password, nickname);

                // 4. api ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค.
                Call<UserRes> call = api.register(user);

                // 5. api๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
                call.enqueue(new Callback<UserRes>() {
                    @Override
                    public void onResponse(Call<UserRes> call, Response<UserRes> response) {
                        Log.i("MEMO REGISTER", ""+response.code());

                        //๋‹ค์ด์–ผ๋กœ๊ทธ๋ฅผ ๋จผ์ € ์—†์•ค๋‹ค.
                        dismissProgress();

                        // 200 OK ์ผ๋•Œ,
                        if(response.isSuccessful()){

                            UserRes userRes = response.body();
                            Log.i("MEMO REGISTER",userRes.accessToken);

                            // ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ํ† ํฐ์„ ์ €์žฅํ•ด์•ผ ํ•œ๋‹ค.
                            SharedPreferences sp = getSharedPreferences(Config.SP_NAME,MODE_PRIVATE);
                            SharedPreferences.Editor editor = sp.edit();
                            editor.putString("token", userRes.accessToken);
                            editor.commit(); //์•ฑ์„ ์‚ญ์ œํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ์˜๊ตฌ์ €์žฅํ•ด์ค€๋‹ค

                            // ํšŒ์›๊ฐ€์ž… ์•กํ‹ฐ๋น„ํ‹ฐ๋Š” ์ข…๋ฃŒ๋ฅผ ํ•˜๊ณ  ๋ฉ”์ธ์•กํ‹ฐ๋น„ํ‹ฐ๋„์šด๋‹ค.
                            Intent intent = new Intent(RegisterActivity.this, MainActivity.class);
                            startActivity(intent);
                            finish();
                            return;


                        }else if(response.code() == 500){
                            Snackbar.make(btnRegister, "์ด๋ฏธ ํšŒ์›๊ฐ€์ž…ํ•œ ์ด๋ฉ”์ผ์ž…๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธํ•˜์„ธ์š”.",
                                    Snackbar.LENGTH_SHORT).show();
                            return;
                        }else {
                            Snackbar.make(btnRegister, "์„œ๋ฒ„์— ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž ์‹œ ํ›„ ๋‹ค์‹œ ์‹œ๋„ํ•˜์„ธ์š”.",
                                    Snackbar.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onFailure(Call<UserRes> call, Throwable throwable) {
                        //๋‹ค์ด์–ผ๋กœ๊ทธ๋ฅผ ๋จผ์ € ์—†์•ค๋‹ค.
                        dismissProgress();

                    }
                });
            }
        });

    }

    // *** ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ฑฐ๋‚˜, ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜, ์‚ญ์ œํ•˜๋Š” ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•œ๋‹ค!
    Dialog dialog;
    void showProgress(){
        dialog = new Dialog(this);
        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        dialog.setContentView(new ProgressBar(this));
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);
        dialog.show();
    }
    void dismissProgress(){
        dialog.dismiss();
    }

}

 

 

 

 

LoginActivity.java

 

๋กœ๊ทธ์ธ ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋ฉด, ๋กœ๊ทธ์ธ ๋˜๋„๋ก postman๊ณผ ์—ฐ๊ฒฐํ•˜๊ธฐ

package com.yujinoh.memo;

import android.app.Dialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.util.Patterns;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import com.google.android.material.snackbar.Snackbar;
import com.yujinoh.memo.api.NetworkClient;
import com.yujinoh.memo.api.UserApi;
import com.yujinoh.memo.config.Config;
import com.yujinoh.memo.model.User;
import com.yujinoh.memo.model.UserRes;

import java.util.regex.Pattern;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

public class LoginActivity extends AppCompatActivity {

    EditText editEmail;
    EditText editPassword;
    TextView txtRegister;
    Button btnLogin;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        editEmail = findViewById(R.id.editEmail);
        editPassword = findViewById(R.id.editPassword);
        txtRegister = findViewById(R.id.txtRegister);
        btnLogin = findViewById(R.id.btnLogin);

        txtRegister.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //ํšŒ์›๊ฐ€์ž… ์•กํ‹ฐ๋น„ํ‹ฐ ์‹คํ–‰
                Intent intent = new Intent(LoginActivity.this, RegisterActivity.class);
                startActivity(intent);
                finish();
            }
        });

        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String email = editEmail.getText().toString().trim();
                String password = editPassword.getText().toString().trim();

                if(email.isEmpty() || password.isEmpty()){
                    Snackbar.make(btnLogin, "ํ•„์ˆ˜ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค. ๋ชจ๋‘ ์ž…๋ ฅํ•˜์„ธ์š”.",Snackbar.LENGTH_SHORT).show();
                    return;
                }

                // ์ด๋ฉ”์ผ ํ˜•์‹ ์ฒดํฌ (ํšŒ์›๊ฐ€์ž…์˜ ์ฝ”๋“œ C&P)
                // ์ž๋ฐ”์˜ ์ด๋ฉ”์ผ ํ˜•์‹ ์ฒดํฌํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ Pattern
                Pattern pattern = Patterns.EMAIL_ADDRESS;
                if(pattern.matcher(email).matches() == false){
                    Snackbar.make(btnLogin,"์ด๋ฉ”์ผ ํ˜•์‹์„ ๋ฐ”๋ฅด๊ฒŒ ์ž‘์„ฑํ•˜์„ธ์š”.",Snackbar.LENGTH_SHORT).show();
                    return;
                }

                // ๋กœ๊ทธ์ธ API ํ˜ธ์ถœ!

                // 0. ๋‹ค์ด์–ผ๋กœ๊ทธ ํ‘œ์‹œํ•œ๋‹ค.
                showProgress();

                // 1. ๋ ˆํŠธ๋กœํ• ๋ณ€์ˆ˜ ๋งŒ๋“ ๋‹ค.
                Retrofit retrofit = NetworkClient.getRetrofitClient(LoginActivity.this);

                // 2. API ๊ฐ์ฒด ์ƒ์„ฑํ•œ๋‹ค
                UserApi api = retrofit.create(UserApi.class);

                // 3. ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ ๋‹ค.
                User user = new User(email, password);

                // 4. api ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค.
                Call<UserRes> call = api.login(user);

                // 5. ๋„คํŠธ์›Œํฌ๋กœ ํ˜ธ์ถœํ•œ๋‹ค
                call.enqueue(new Callback<UserRes>() {
                    @Override
                    public void onResponse(Call<UserRes> call, Response<UserRes> response) {
                        dismissProgress();

                        if(response.isSuccessful()){

                            UserRes userRes = response.body();

                            // ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ํ† ํฐ์„ ์ €์žฅํ•ด์•ผ ํ•œ๋‹ค.
                            SharedPreferences sp = getSharedPreferences(Config.SP_NAME,MODE_PRIVATE);
                            SharedPreferences.Editor editor = sp.edit();
                            editor.putString("token", userRes.accessToken);
                            editor.commit(); //์•ฑ์„ ์‚ญ์ œํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ์˜๊ตฌ์ €์žฅํ•ด์ค€๋‹ค

                            // ํšŒ์›๊ฐ€์ž… ์•กํ‹ฐ๋น„ํ‹ฐ๋Š” ์ข…๋ฃŒ๋ฅผ ํ•˜๊ณ  ๋ฉ”์ธ์•กํ‹ฐ๋น„ํ‹ฐ๋„์šด๋‹ค.
                            Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                            startActivity(intent);
                            finish();
                            return;

                        }else{
                            Snackbar.make(btnLogin, "์„œ๋ฒ„์— ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž ์‹œ ํ›„ ๋‹ค์‹œ ์‹œ๋„ํ•˜์„ธ์š”.",
                                    Snackbar.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onFailure(Call<UserRes> call, Throwable throwable) {
                        dismissProgress();
                        // ์œ ์ €์—๊ฒŒ ์•Œ๋ฆฌ๊ณ  ๋กœ๊ทธ๋‚จ๊ธฐ๊ณ  ๋ฆฌํ„ด

                    }
                });


            }
        });

    }

    // *** ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ฑฐ๋‚˜, ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜, ์‚ญ์ œํ•˜๋Š” ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•œ๋‹ค!
    Dialog dialog;
    void showProgress(){
        dialog = new Dialog(this);
        dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        dialog.setContentView(new ProgressBar(this));
        dialog.setCancelable(false);
        dialog.setCanceledOnTouchOutside(false);
        dialog.show();
    }
    void dismissProgress(){
        dialog.dismiss();
    }

}

 

 

 

 

 

๋กœ๊ทธ์•„์›ƒ ๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ

 

menu ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๊ณ , xml ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์„œ ์•ก์…˜๋ฐ”์— ์•„์ด์ฝ˜์„ ๋„ฃ์œผ๋ ค๊ณ  ํ•œ๋‹ค.

 

 



 

https://codebunny99.tistory.com/139

 

์•ก์…˜๋ฐ”(Actionbar) ์ด๋ฆ„, ์ƒ‰, ๋ฐฑ๋ฒ„ํŠผ, ์•„์ด์ฝ˜ ๋””์ž์ธ๊ณผ ์‚ญ์ œ ๋ฐฉ๋ฒ•

์•ก์…˜๋ฐ” ์ƒ‰ ๋ฐ”๊พธ๊ธฐ    name๋„ ์ž์‹ ์ด ์ง€์ •ํ•˜์—ฌ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.      ์•ก์…˜๋ฐ” ์ด๋ฆ„ ๋ฐ”๊พธ๊ธฐ MainActivity.java ์—์„œgetSupportActionBar().setTitle("ํฌ์ŠคํŒ… ๋ฆฌ์ŠคํŠธ");  + // ์•ก์…˜๋ฐ”์— ํ™”์‚ดํ‘œ ๋ฐฑ๋ฒ„ํŠผ์„ ํ‘œ์‹œํ•˜๋Š”

codebunny99.tistory.com

 

์•ก์…˜๋ฐ” ์•„์ด์ฝ˜ ์ถ”๊ฐ€๋ฅผ ์ฐธ๊ณ ํ•œ๋‹ค.

 

 

 

 

UserApi ์— ๋กœ๊ทธ์•„์›ƒ API๋ฅผ ์ž…๋ ฅํ•ด์ค€๋‹ค.

 

 

 

 


MainActivity์— ์ž‘์„ฑํ•ด์ฃผ๊ธฐ

 

package com.~.memo;

import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.~.memo.adapter.MemoAdapter;
import com.~.memo.api.MemoApi;
import com.~.memo.api.NetworkClient;
import com.~.memo.api.UserApi;
import com.~.memo.config.Config;
import com.~.memo.model.Memo;
import com.~.memo.model.MemoList;
import com.~.memo.model.UserRes;

import java.util.ArrayList;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;


public class MainActivity extends AppCompatActivity {

    ProgressBar progressBar;
    Button btnAdd;
    RecyclerView recyclerView;
    ArrayList<Memo> memoArrayList = new ArrayList<>();
    MemoAdapter adapter;


    String token;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // ๋กœ๊ทธ์ธ์„ ํ•œ ์œ ์ €์ธ์ง€ ์•„๋‹Œ์ง€๋ฅผ ์ฒดํฌํ•œ๋‹ค.
        // ๋กœ๊ทธ์ธ์„ ์•ˆํ–ˆ์œผ๋ฉด, ๋กœ๊ทธ์ธ ์•กํ‹ฐ๋น„ํ‹ฐ๋ฅผ ๋„์šฐ๊ณ ,
        // ๋กœ๊ทธ์ธ์„ ํ–ˆ์œผ๋ฉด, ์ธ์ฆํ† ํฐ์„ ๊ฐ€์ ธ์˜จ๋‹ค.

        SharedPreferences sp = getSharedPreferences(Config.SP_NAME, MODE_PRIVATE);
        token = sp.getString("token", "");

        if(token.isEmpty()){
            // ๋กœ๊ทธ์ธ ์•กํ‹ฐ๋น„ํ‹ฐ๋ฅผ ๋„์šด๋‹ค.
            Intent intent = new Intent(MainActivity.this, LoginActivity.class);
            startActivity(intent);
            finish();
            return;
        }

        progressBar = findViewById(R.id.progressBar);
        btnAdd = findViewById(R.id.btnAdd);
        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));

        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override

            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, AddActivity.class);
                startActivity(intent);
            }
        });

        // ๋‚ด ๋ฉ”๋ชจ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
        getNetworkData();

    }

    private void getNetworkData() {

        Retrofit retrofit = NetworkClient.getRetrofitClient(MainActivity.this);

        MemoApi api = retrofit.create(MemoApi.class);

        Call<MemoList> call = api.getMemoList("Bearer "+token);

        call.enqueue(new Callback<MemoList>() {
            @Override
            public void onResponse(Call<MemoList> call, Response<MemoList> response) {
                progressBar.setVisibility(View.GONE);

                if(response.isSuccessful()){

                    MemoList memoList = response.body();

                    // ๋น„์–ด์žˆ๋Š” ์–ด๋ ˆ์ด๋ฆฌ์ŠคํŠธ์—, ๋ฐ›์•„์˜จ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋‹ด์•„์ค€๋‹ค!

                    memoArrayList.addAll( memoList.getItems() );

                    // ๋ฐ์ดํ„ฐ๊ฐ€ ์ค€๋น„ ์™„๋ฃŒ ๋˜์—ˆ์œผ๋‹ˆ,
                    // ์–ด๋ށํ„ฐ ๋งŒ๋“ค์–ด์„œ, ๋ฆฌ์‚ฌ์ดํด๋Ÿฌ๋ทฐ์— ์ ์šฉํ•œ๋‹ค.
                    adapter = new MemoAdapter(MainActivity.this, memoArrayList);
                    recyclerView.setAdapter(adapter);


                }else {

                }

            }

            @Override
            public void onFailure(Call<MemoList> call, Throwable throwable) {
                progressBar.setVisibility(View.GONE);
            }
        });

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {

        if( item.getItemId() == R.id.menuLogout ){

            showAlertDialog();

        }


        return super.onOptionsItemSelected(item);
    }

    void showAlertDialog(){
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setCancelable(true);
        builder.setTitle("๋กœ๊ทธ์•„์›ƒ");
        builder.setMessage("์ •๋ง ๋กœ๊ทธ์•„์›ƒ ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ??");
        builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

                // ๋กœ๊ทธ์•„์›ƒ API ํ˜ธ์ถœ!

                Retrofit retrofit = NetworkClient.getRetrofitClient(MainActivity.this);

                UserApi api = retrofit.create(UserApi.class);

                Call<UserRes> call = api.logout("Bearer " + token);

                call.enqueue(new Callback<UserRes>() {
                    @Override
                    public void onResponse(Call<UserRes> call, Response<UserRes> response) {
                        if(response.isSuccessful()){

                            SharedPreferences sp = getSharedPreferences(Config.SP_NAME, MODE_PRIVATE);
                            SharedPreferences.Editor editor = sp.edit();
                            editor.putString("token", "");
                            editor.commit();

                            Intent intent = new Intent(MainActivity.this, LoginActivity.class);
                            startActivity(intent);

                            finish();
                            return;


                        }else{

                        }
                    }

                    @Override
                    public void onFailure(Call<UserRes> call, Throwable throwable) {

                    }
                });


            }
        });
        builder.setNegativeButton("No", null);
        builder.show();
    }
}