3월 7~8일(1)

SJY0000·2022년 3월 9일
0

Android

목록 보기
6/15

오늘 배운 것

  • Android Studio로 TODO Project App 만들기(1)

첫 화면 만들기

배경은 Drawble 파일을 만들어서 그라데이션 색의 배경만들기

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:startColor="#E4A1A1"
        android:centerColor="#3250B4"
        android:endColor="#254095"
        android:angle="90"
        android:centerY="0.5"
        />
    <corners android:radius="2dp" />
</shape>

로고는 iconfinder.com에서 검색해서 SVG 파일을 다운받는다.

defaultConfig안에 하위버전에서도 SVG 이미지를 사용할 수 있도록 구문을 입력한다.

SVG 파일 사용방법

1) Android Studio는 앞에 숫자로 시작하는 파일을 사용 할 수 없기 때문에 숫자로 시작하지않도록 파일명을 변경해준다.

2) drawable 폴더에서 오른쪽 마우스 클릭한다.

3) New -> Vector Asset을 클릭하고 path에서 svg파일을 선택한다.(프로젝트 폴더안에 임시로 복사해두고 선택해도 됨)

4) 만들어진 아이콘.XML 파일에서 수정할 부분 수정하고 평범한 이미지처럼 사용하면 됨

SVG와 png,img파일과 다른점

png 나 img파일 등은 pixel로 표현되서 출력하는 기기에 따라 해상도가 달라져서 그림이 지저분하게 보일 수 있지만 SVG파일은 그림을 만드는 데이터가 적혀 있기 때문에 해상도가 달라져도 Pixel이 보이거나 하지않고 부드럽게 보인다.


progressbar는 병렬처리(Thread)를 이용하여 동시에 실행될 수 있도록 함

자동로그인 체크데이터를 Login화면이 실행되기 전 단계에서 미리 확인하고 처리 할 수 있도록 함


package com.example.todo;

import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.ProgressBar;

public class LogoActivity extends AppCompatActivity {

    private ProgressBar progressBar;
    private int progress;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_logo);
        // 액션바 숨기기
        ActionBar actionBar = getSupportActionBar(); // Support를 붙여서 하위버전도 동작하게 해야함
        actionBar.hide();

        // 안드로이드에서는 기존 UI스레드는 Thread.sleep() 호출을 허용하지 않으므로
        // 별도의 작업스레드를 생성하여 실행함
        progressBar = findViewById(R.id.progressBar);
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // 프로그레스바 보이기 한 후 일정시간 주기로 채우기
                processProgressBar();
                // rememberMe 자동 로그인 값에 따라 로그인화면 또는 메인화면 띄우기
                processRememberMe();

            }
        });
        thread.start();

        // SharedPreferences 파일 데이터 모두 삭제하기
//        clearRememberMe();
    } // onCreate

    private void clearRememberMe() {
        SharedPreferences pref = getSharedPreferences("todo", Activity.MODE_PRIVATE);
        SharedPreferences.Editor editor =  pref.edit();
        editor.clear(); // 파일 데이터 모두 삭제
        editor.commit();
    }// clearRememberMe


    private void processProgressBar() {

        try {
            Thread.sleep(2000); // 2000ms = 2초 쉬고 프로그레스바 나타남
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // Android는 View 객체 접근은 UI스레드에서만 가능함
        // 작업스레드(activity)에서는 View객체 접근이 허용안됨
        // 사용하려면 runOnUiThread를 사용해야 접근가능함
        // runOnUiThread() 메소드를 통해 UI 스레드로 실행흐름을 옮겨야 함.
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressBar.setVisibility(View.VISIBLE);
            }
        });
        // 람다식
//        runOnUiThread(()-> progressBar.setVisibility(View.VISIBLE));
        for (progress = 1; progress <= 100; progress++) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    progressBar.setProgress(progress);
                }
            });

            try {
                Thread.sleep(10); // 10ms 쉬고 다음 반복 실행
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }// for

    } // processProgressBar

    private void processRememberMe() {
        // 기존에 저장되어 있던 자동로그인 값을 SharedPreferences로부터 가져오기
        SharedPreferences pref = getSharedPreferences("todo", Activity.MODE_PRIVATE);
        Intent intent = null;
        if (pref == null || !pref.contains("rememberMe")) {
            // 로그인 Activity 띄우기
            intent = new Intent(getApplicationContext(), LoginActivity.class);
        } else { // pref != null || pref.contains("rememberMe")
            boolean isRememberMe = pref.getBoolean("rememberMe", false);
            String id = pref.getString("loginId", "");

            if (isRememberMe == true) {
                intent = new Intent(this, MainActivity.class);
                intent.putExtra("loginId", id);
            }
        }
        startActivity(intent);

        // 현재 액티비티 닫기(뒤로가기 해도 뜨지않음)
        finish();
    } // processRememberMe
}

회원가입 화면 만들기

  • 저번에 만들었는 REST API 서버를 활용하여 Android Studio에서 Retrofit 라이브러리를 이용하여 데이터를 전송하고 받을 수 있게함
  • App은 처음 최소한의 권한 만을 가지고 있기 때문에 인터넷을 연결 하려면 권한을 획득 할 수 있게 해야함

Android Manifest에 인터넷 접속 권한 얻으려면 application 태그 위에 uses-permission 태그를 넣어주고 설정을 추가한다.

Retrofit 라이브러리를 사용하기 위해 build.gradle(module.파일명)에 dependencies 안에 mvnrepository.com 에서 gradle(short) 탭의 구문을 복사하여 붙여넣는다.

회원가입 화면

  • TODO Project의 User bean(model)들을 복사하여 메인폴더 안에 복사하여 객체형식을 갖추도록 함
  • Retrofit은 Java Script의 Ajax기능과 같은 기능을 하기때문에 입력한 id 입력창에 포커스가 사라지면 중복체크하여 표시하도록 함

package com.example.todo;

import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.example.todo.domain.User;
import com.example.todo.domain.UserOneResult;
import com.example.todo.domain.UserResult;
import com.example.todo.retrofit.RetrofitClient;
import com.example.todo.retrofit.UserService;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class JoinActivity extends AppCompatActivity {

    public static  final String TAG = "Join";
    private boolean isIdDuplicated;
    private TextView idCheck;
    private EditText firstJoin,lastJoin,idJoin,passwordJoin;
    private RadioButton rdoMale,rdoFemale;
    private RadioGroup radioGroup;
    private String gender;

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

        idCheck = findViewById(R.id.idCheck);
        firstJoin = findViewById(R.id.firstJoin);
        lastJoin = findViewById(R.id.lastJoin);
        idJoin = findViewById(R.id.idJoin);
        passwordJoin = findViewById(R.id.passwordJoin);
        rdoMale = findViewById(R.id.rdoMale);
        rdoFemale = findViewById(R.id.rdoFemale);
        radioGroup = findViewById(R.id.radioGroup);

        ActionBar actionBar = getSupportActionBar(); // Support를 붙여서 하위버전도 동작하게 해야함
        actionBar.hide();

        // 라디오그룹안에 있는 라디오버튼 체크변화
        radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int resId) { // resID = 리소스아이디
                if (resId == R.id.rdoMale) {
                    gender = "남";
                } else if (resId == R.id.rdoFemale) {
                    gender = "여";
                }
                Log.d(TAG,"onCheckedChanged() 호출됨 - gender = " + gender); // 로그에 출력
            }
        });

        // 가입하기버튼을 눌렀을 때
        Button btnJoinComplete = findViewById(R.id.btnJoinComplete);
        btnJoinComplete.setOnClickListener(view -> processJoin());
        // 취소버튼을 눌렀을 때
        Button btnJoinCancel = findViewById(R.id.btnJoinCancel);
        btnJoinCancel.setOnClickListener(view -> finish());

        idJoin.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View view, boolean hasFocus) { // 포커스가 변경 되었을 때
//                EditText editText = (EditText) view; = idJoin.getText().toString().trim();
                if (!hasFocus) { // hasFocus == false
                    String id = idJoin.getText().toString().trim();
                    if (id.length() == 0) {
                        return;
                    }
                    checkDuplicateId(id);
                }
            } // onFocusChange
        });
    }// onCreate

    private void checkDuplicateId(String id) {
        UserService userService = RetrofitClient.getUserService();

        Call<UserOneResult> call = userService.getUser("one",id);

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

                if (response.isSuccessful()) {
                    UserOneResult userOneResult = response.body();
                    if (userOneResult.isHasResult()) { // 중복
                        idCheck.setText("존재하는 아이디 입니다.");
                        idCheck.setTextColor(Color.RED);
                        isIdDuplicated = true;
//                        if (response.isSuccessful()) {
//                            UserOneResult userOneResult = response.body();
//                            isIdDuplicated = userOneResult.isHasResult();
//
//                            processResponseDupId(isIdDuplicated);
//                        }
                    } else { // 중복아님
                        idCheck.setText("존재하지 않는 아이디입니다.");
                        idCheck.setTextColor(Color.GREEN);
                        isIdDuplicated = false;
                    }
                }
            }

            @Override
            public void onFailure(Call<UserOneResult> call, Throwable t) {

            }
        });
    }

    // 회원가입 페이지에 적은 데이터 전송
    private void processJoin() {
        String id = idJoin.getText().toString().trim(); // 아이디(userName)가져오기
        String pwd = passwordJoin.getText().toString().trim(); // 비밀번호(password)가져오기
        String firstName = firstJoin.getText().toString().trim(); // 성(firstName)가져오기
        String lastName = lastJoin.getText().toString().trim(); // 이름(lastName)가져오기

//         라디오버튼 선택값으로 성별정보 구하기
        String gender = "";
        if (rdoMale.isChecked()) {
            gender = "남";
        } else if (rdoFemale.isChecked()) {
            gender = "여";
        }
        // 사용자 입력값 검증하기
        boolean isSafe = validateUserInput(id, pwd, firstName, lastName);
        if (!isSafe) { // isSafe == false
            return;
        }
        // 입력값을 User 객체로 변환하기
        User user = new User();
        user.setFirstName(firstName);
        user.setLastName(lastName);
        user.setUserName(id);
        user.setPassword(pwd);
        // User 객체를 서버에 전송하기
        insertUser(user);
//        if (id.length() == 0) {
//            firstJoin.requestFocus(); // 포커스 주기
//                firstJoin.selectAll(); // 선택해서 포커스
//        }
    } // processJoin

    // 회원가입 시 항목 체크
    private boolean validateUserInput(String id, String pwd, String firstName, String lastName) {
        // 입력값이 하나라도 없으면 메시지로 알리고 회원가입 취소하기
        if(id.length() == 0 || pwd.length() == 0 || firstName.length() == 0 || lastName.length() == 0){
            Toast.makeText(this,"입력하지 않은 항목이 있습니다.",Toast.LENGTH_LONG).show();
            return false;
        } else {
            // 아이디 중복여부 확인
            if(isIdDuplicated) { //isIdDuplicated == true
                Toast.makeText(this, "이미 사용중인 아이디 입니다.", Toast.LENGTH_LONG).show();
                idJoin.requestFocus();
                return false;
            }
            return true;
        }



    }// validateUserInput

    private void insertUser(User user) {
        UserService userService = RetrofitClient.getUserService();

        Call<UserResult> call = userService.createUser(user);

        call.enqueue(new Callback<UserResult>() {
            @Override
            public void onResponse(Call<UserResult> call, Response<UserResult> response) {
                if (!response.isSuccessful()) {
                    Log.d(TAG, "onResponse : 실패 ");
                    return;
                }
               UserResult userResult = response.body();
                Log.d(TAG, "onResponse : 성공, 응답결과 :  " + userResult.toString());
                if (userResult.isSuccess()) {
                    showJoinMessage();
                }
            } // onResponse

            @Override
            public void onFailure(Call<UserResult> call, Throwable t) {
                Log.d(TAG, "onFailure : " + t.getMessage());
            }
        });
    } // insertUser

    public void showJoinMessage() {
        AlertDialog alertDialog = new AlertDialog.Builder(this)
                .setTitle("회원가입 성공")
                .setMessage("회원가입이 완료되었습니다.")
                .setIcon(android.R.drawable.ic_dialog_info)
                .setPositiveButton("확인", (dialogInterface, i) -> finish())
                .create(); // 경고창 설정 및 객체생성
        alertDialog.show(); // 경고창 띄우기

    } // showJoinMessage
}

0개의 댓글

관련 채용 정보