국비교육(22-23)

105일차(1)/Android App(70) : 모바일 갤러리 기능 구현(4)

서리/Seori 2023. 3. 11. 01:02

105일차(1)/Android App(70) : 모바일 갤러리 기능 구현(4)

 

2023.03.09 - [국비교육] - 104일차(1)/Android App(69) : 모바일 갤러리 기능 구현(3)

 

 

- Http 요청을 할 유틸리티 생성

 

 

- 생성자에서 Context를 받아준다. Activity나 Service를 받아서 사용하면 된다!

 

 

- 안드로이드 운영체제에는 SQLiteDB가 기본적으로 만들어져 들어있다.

- 저 "CookieDB.sqlite" 가 하나의 계정이라고 생각하면 된다. 이 안에 파일, 테이블 등이 들어있다.

- 이 계정의 데이터를 SQLiteDB에서 해석하여 사용하는 것!

 

 

- 이 안에서 진행되는 비동기작업에 대한 리스너 인터페이스를 만들어주었다.

- 각각 성공했을 때, 실패했을 때 호출되는 메소드

 

- 이 유틸리티를 사용하는 곳에서는 이 인터페이스를 구현해야 한다!

- 그러면 아래의 DBHelper의 작업 안에서 성공하면 onSuccess() 어떤 정보를 넣어주고, 실패하면 onFail() 안에 정보를 넣어준다.

 

 

- 쿠키이름과 쿠키를 DB에 저장.

- 쿠키이름은 겹치면 안되므로 PK로 지정

- key = value : key2 = value2 이런 형태의 문자열로 저장된다.

 

 

 

- 쿠키이름 키값만 빼내서 cookie_name 칼럼에 담고, 쿠키 전체를 cookie 칼럼에 담는다

 

 

- 테이블을 삭제하고 onCreate에서 재생성. 즉 그러면 테이블을 업데이트하는 효과를 낼 수 있다.

 

 

- 인자 4개! 요청의 아이디값, Url 경로, Map(안에 요청파라미터 담아둠), 작업의 성공/실패 여부 리턴할 리스너

 

 

- MyHttpUtil 을 호출해서 사용할 때 요청 id, 요청 url 을 이렇게 넣어서 사용하면 된다.

 

 

- 메소드의 인자로 받은 내용들을 GetRequestTask에 전달해준다.

- AsyncTask에서 파라미터 타입을 맵이라고 지정해놨기 때문에 이렇게 전달 가능한 것!!

 

 

- ... 은 이렇게 사용가능하다. 동적 인자 받기 (인자의 개수가 정해져있지 않음)

- arg가 0번방, 1번방, 2번방에 각각 저장되는 것이라고 보면 된다.

 


 

MyHttpUtil

package com.example.step25imagecapture.util;

import android.content.AsyncQueryHandler;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.AsyncTask;
import android.util.Log;

import androidx.annotation.Nullable;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/*
    - Http 요청을 할때 서버가 응답하는 쿠키를 모두 읽어서 저장하고 싶다
    - 다음번 Http 요청을 할때 저장된 쿠키를 모두 보내고 싶다
    - 쿠키 값이 수정되어서 응답되면 저장되어 있는 쿠키를 수정해야 한다.
    - 그러면 쿠키를 SQLiteDataBase 를 활용해서 관리하면 빠르게 처리 할수 있지 않을까?
 */
public class MyHttpUtil {
    //필드
    private Context context;
    private DBHelper dbHelper;
    //생성자
    public MyHttpUtil(Context context){
        this.context=context;
        //DBHelper 객체의 참조값을 얻어내서 필드에 저장해 둔다.
        dbHelper=new DBHelper(context, "CookieDB.sqlite", null, 1);
    }
    //이 유틸리티를 사용하는 곳에서 구현해야 하는 인터페이스
    public interface RequestListener{
        public void onSuccess(int requestId, String data);
        public void onFail(int requestId, Map<String, Object> result);
    }

    class DBHelper extends SQLiteOpenHelper{

        public DBHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);
        }
        //해당 DBHelper 를 처음 사용할때 호출되는 메소드 (new DBHelper() 를 처음 호춯할때)
        @Override
        public void onCreate(SQLiteDatabase db) {
            //테이블을 만들면 된다.
            String sql="CREATE TABLE board_cookie (cookie_name TEXT PRIMARY KEY, cookie TEXT)";
            db.execSQL(sql);
        }
        //DB 를 리셋(업그래이드)할때 호출되는 메소드
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            //업그래이드할 내용을 작성하면 된다.
            db.execSQL("DROP TABLE IF EXISTS board_cookie"); //만일 테이블이 존재하면 삭제한다.
            //다시 만들어 질수 있도록 onCreate() 메소드를 호출한다.
            onCreate(db);
        }
    }
    /*
        GET 방식 요청을 하는 메소드
     */
    public void sendGetRequest(int requestId, String requestUrl, Map<String, String> params,
                               RequestListener listener){
        //GET 방식 요청을 할 비동기 Task 객체를 생성해서
        GetRequestTask task=new GetRequestTask();
        //필요한 값을 넣어주고
        task.setRequestId(requestId);
        task.setRequestUrl(requestUrl);
        task.setListener(listener);
        //비동기 Task 를 실행한다.
        task.execute(params);
    }
    /*
        POST 방식 요청을 하는 메소드
    */
    public void sendPostRequest(int requestId, String requestUrl, Map<String, String> params,
                               RequestListener listener){
        //POST 방식 요청을 할 비동기 Task 객체를 생성해서
        PostRequestTask task=new PostRequestTask();
        //필요한 값을 넣어주고
        task.setRequestId(requestId);
        task.setRequestUrl(requestUrl);
        task.setListener(listener);
        //비동기 Task 를 실행한다.
        task.execute(params);
    }

    private class GetRequestTask extends AsyncTask<Map<String, String>, Void, String>{
        //필요한 필드 구성
        private int requestId;
        private String requestUrl;
        private RequestListener listener;

        public void setRequestId(int requestId) {
            this.requestId = requestId;
        }

        public void setRequestUrl(String requestUrl) {
            this.requestUrl = requestUrl;
        }

        public void setListener(RequestListener listener) {
            this.listener = listener;
        }

        @Override
        protected String doInBackground(Map<String, String>... maps) {
            //maps 배열의 0 번방에 GET 방식 요청 파라미터가 들어 있다.
            //파라미터가 없으면 null 이 전달될 예정
            Map<String, String> param = maps[0];
            if(param!=null){//요청 파리미터가 존재 한다면
                //서버에 전송할 데이터를 문자열로 구성하기
                StringBuffer buffer=new StringBuffer();
                //Map 에 존재하는 key 값을 Set 에 담아오기
                Set<String> keySet=param.keySet();
                Iterator<String> it=keySet.iterator();
                boolean isFirst=true;
                //반복문 돌면서 map 에 담긴 모든 요소를 전송할수 있도록 구성한다.
                while(it.hasNext()){
                    String key=it.next();
                    String arg=null;
                    //파라미터가 한글일 경우 깨지지 않도록 하기 위해.
                    String encodedValue=null;
                    try {
                        encodedValue= URLEncoder.encode(param.get(key), "utf-8");
                    } catch (UnsupportedEncodingException e) {}
                    if(isFirst){
                        arg="?"+key+"="+encodedValue;
                        isFirst=false;
                    }else{
                        arg="&"+key+"="+encodedValue;
                    }
                    buffer.append(arg);
                }
                String data=buffer.toString();
                //GET 방식 요청 파라미터를 요청 url 뒤에 연결한다.
                requestUrl +=data;
            }
            //서버가 http 요청에 대해서 응답하는 문자열을 누적할 객체
            StringBuilder builder=new StringBuilder();
            HttpURLConnection conn=null;
            InputStreamReader isr=null;
            BufferedReader br=null;
            try{
                //URL 객체 생성
                URL url=new URL(requestUrl);
                //HttpURLConnection 객체의 참조값 얻어오기
                conn=(HttpURLConnection)url.openConnection();
                if(conn!=null){
                    conn.setConnectTimeout(20000); //응답을 기다리는 최대 대기 시간
                    conn.setRequestMethod("GET");//Default 설정
                    conn.setUseCaches(false);//케쉬 사용 여부
                    //저장된 쿠키가 있다면 읽어내서 쿠키도 같이 보내기
                    SQLiteDatabase db=dbHelper.getReadableDatabase();
                    String sql="SELECT cookie FROM board_cookie";
                    //select 된 결과를 Cursor 에 담아온다.
                    Cursor cursor=db.rawQuery(sql, null);
                    while(cursor.moveToNext()){
                        String cookie=cursor.getString(0);
                        conn.addRequestProperty("Cookie", cookie);
                    }
                    //응답 코드를 읽어온다. (200, 404, 500 등등의 값)
                    int responseCode=conn.getResponseCode();
                    if(responseCode==200){
                        //서버가 출력하는 문자열을 읽어오기 위한 객체
                        isr=new InputStreamReader(conn.getInputStream());
                        br=new BufferedReader(isr);
                        //반복문 돌면서 읽어오기
                        while(true){
                            //한줄씩 읽어들인다.
                            String line=br.readLine();
                            //더이상 읽어올 문자열이 없으면 반복문 탈출
                            if(line==null)break;
                            //읽어온 문자열 누적 시키기
                            builder.append(line);
                        }
                    }else if(responseCode==301 || responseCode==302 || responseCode==303){
                        //리다일렉트 요청할 경로를 얻어내서
                        String location=conn.getHeaderField("Location");
                        //해당 경로로 다시 요청을 해야 한다.

                    }else if(responseCode >= 400 && responseCode < 500){
                        //요청 오류인 경우에 이 요청은 실패!

                    }else if(responseCode == 500){
                        //서버의 잘못된 동작으로 인한 요청 실패!

                    }
                }
                //서버가 응답한 쿠키 목록을 읽어온다.
                List<String> cookList=conn.getHeaderFields().get("Set-Cookie");
                //만일 쿠키가 존재 한다면
                if(cookList != null){
                    //반복문 돌면서 DB 에 저장한다.
                    //새로 응답된 쿠키라면 insert, 이미 존재하는 쿠키라면 update
                    SQLiteDatabase db=dbHelper.getWritableDatabase();
                    for(String cookie:cookList){
                        //쿠키의 이름
                        String cookie_name=cookie.split("=")[0];
                        //쿠키의 이름을 String[] 에 담고
                        String[] arg={cookie_name};
                        //해당 쿠키가 이미 존재하는지 select 해 본다.
                        Cursor cursor=db.rawQuery("SELECT * FROM board_cookie WHERE cookie_name=?", arg);
                        //select 된 row 의 갯수
                        int selectRow=cursor.getCount();
                        if(selectRow == 0){//새로운 쿠키이면 저장
                            Object[] args={cookie_name, cookie};
                            db.execSQL("INSERT INTO board_cookie (cookie_name, cookie) VALUES(?, ?)", args);
                        }else{//이미 존재하는 쿠키이면 수정
                            Object[] args={cookie, cookie_name};
                            db.execSQL("UPDATE board_cookie SET cookie=? WHERE cookie_name=?", args);
                        }
                    }
                    // .close() 해야지만 실제로 반영된다.
                    db.close();
                }

            }catch(Exception e){
                Log.e("MyHttpUtil.sendGetRequest()", e.getMessage());
            }finally {
                try{
                    if(isr!=null)isr.close();
                    if(br!=null)br.close();
                    if(conn!=null)conn.disconnect();
                }catch(Exception e){}
            }
            //응답받은 문자열을 리턴한다.
            return builder.toString();
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            //RequestListener 객체에(액티비티 or 서비스 or 프레그먼트 .. ) 넣어주기
            listener.onSuccess(requestId, s);
        }
    }


    private class PostRequestTask extends AsyncTask<Map<String, String>, Void, String>{
        //필요한 필드 구성
        private int requestId;
        private String requestUrl;
        private RequestListener listener;

        public void setRequestId(int requestId) {
            this.requestId = requestId;
        }

        public void setRequestUrl(String requestUrl) {
            this.requestUrl = requestUrl;
        }

        public void setListener(RequestListener listener) {
            this.listener = listener;
        }

        @Override
        protected String doInBackground(Map<String, String>... maps) {
            //maps 배열의 0 번방에 GET 방식 요청 파라미터가 들어 있다.
            //파라미터가 없으면 null 이 전달될 예정
            Map<String, String> param = maps[0];
            //query 문자열을 누젓 시킬 StringBuffer
            StringBuffer buffer=new StringBuffer();
            if(param!=null){//요청 파리미터가 존재 한다면
                //서버에 전송할 데이터를 문자열로 구성하기
                //Map 에 존재하는 key 값을 Set 에 담아오기
                Set<String> keySet=param.keySet();
                Iterator<String> it=keySet.iterator();
                boolean isFirst=true;
                //반복문 돌면서 map 에 담긴 모든 요소를 전송할수 있도록 구성한다.
                while(it.hasNext()){
                    String key=it.next();
                    String arg=null;
                    //파라미터가 한글일 경우 깨지지 않도록 하기 위해.
                    String encodedValue=null;
                    try {
                        encodedValue= URLEncoder.encode(param.get(key), "utf-8");
                    } catch (UnsupportedEncodingException e) {}
                    if(isFirst){
                        arg=key+"="+encodedValue;
                        isFirst=false;
                    }else{
                        arg="&"+key+"="+encodedValue;
                    }
                    //query 문자열을 StringBuffer 에 누적 시키기
                    buffer.append(arg);
                }
            }
            //post 방식으로 전송할때 사용할 query문자열
            String queryString=buffer.toString();

            //서버가 http 요청에 대해서 응답하는 문자열을 누적할 객체
            StringBuilder builder=new StringBuilder();
            HttpURLConnection conn=null;
            InputStreamReader isr=null;
            BufferedReader br=null;
            PrintWriter pw=null;
            try{
                //URL 객체 생성
                URL url=new URL(requestUrl);
                //HttpURLConnection 객체의 참조값 얻어오기
                conn=(HttpURLConnection)url.openConnection();
                if(conn!=null){
                    conn.setConnectTimeout(20000); //응답을 기다리는 최대 대기 시간
                    conn.setRequestMethod("POST");//POST 방식
                    conn.setUseCaches(false);//케쉬 사용 여부
                    //저장된 쿠키가 있다면 읽어내서 쿠키도 같이 보내기
                    SQLiteDatabase db=dbHelper.getReadableDatabase();
                    String sql="SELECT cookie FROM board_cookie";
                    //select 된 결과를 Cursor 에 담아온다.
                    Cursor cursor=db.rawQuery(sql, null);
                    while(cursor.moveToNext()){
                        String cookie=cursor.getString(0);
                        conn.addRequestProperty("Cookie", cookie);
                    }
                    //전송하는 데이터에 맞게 값 설정하기
                    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); //폼전송과 동일
                    //출력할 스트림 객체 얻어오기
                    OutputStreamWriter osw=
                            new OutputStreamWriter(conn.getOutputStream());
                    //문자열을 바로 출력하기 위해 osw 객체를 PrintWriter 객체로 감싼다
                    pw=new PrintWriter(osw);
                    //서버로 출력하기
                    pw.write(queryString);
                    pw.flush();

                    //응답 코드를 읽어온다. (200, 404, 500 등등의 값)
                    int responseCode=conn.getResponseCode();
                    if(responseCode==200){
                        //서버가 출력하는 문자열을 읽어오기 위한 객체
                        isr=new InputStreamReader(conn.getInputStream());
                        br=new BufferedReader(isr);
                        //반복문 돌면서 읽어오기
                        while(true){
                            //한줄씩 읽어들인다.
                            String line=br.readLine();
                            //더이상 읽어올 문자열이 없으면 반복문 탈출
                            if(line==null)break;
                            //읽어온 문자열 누적 시키기
                            builder.append(line);
                        }
                    }else if(responseCode==301 || responseCode==302 || responseCode==303){
                        //리다일렉트 요청할 경로를 얻어내서
                        String location=conn.getHeaderField("Location");
                        //해당 경로로 다시 요청을 해야 한다.

                    }else if(responseCode >= 400 && responseCode < 500){
                        //요청 오류인 경우에 이 요청은 실패!

                    }else if(responseCode == 500){
                        //서버의 잘못된 동작으로 인한 요청 실패!

                    }
                }
                //서버가 응답한 쿠키 목록을 읽어온다.
                List<String> cookList=conn.getHeaderFields().get("Set-Cookie");
                //만일 쿠키가 존재 한다면
                if(cookList != null){
                    //반복문 돌면서 DB 에 저장한다.
                    //새로 응답된 쿠키라면 insert, 이미 존재하는 쿠키라면 update
                    SQLiteDatabase db=dbHelper.getWritableDatabase();
                    for(String cookie:cookList){
                        //쿠키의 이름
                        String cookie_name=cookie.split("=")[0];
                        //쿠키의 이름을 String[] 에 담고
                        String[] arg={cookie_name};
                        //해당 쿠키가 이미 존재하는지 select 해 본다.
                        Cursor cursor=db.rawQuery("SELECT * FROM board_cookie WHERE cookie_name=?", arg);
                        //select 된 row 의 갯수
                        int selectRow=cursor.getCount();
                        if(selectRow == 0){//새로운 쿠키이면 저장
                            Object[] args={cookie_name, cookie};
                            db.execSQL("INSERT INTO board_cookie (cookie_name, cookie) VALUES(?, ?)", args);
                        }else{//이미 존재하는 쿠키이면 수정
                            Object[] args={cookie, cookie_name};
                            db.execSQL("UPDATE board_cookie SET cookie=? WHERE cookie_name=?", args);
                        }
                    }
                    // .close() 해야지만 실제로 반영된다.
                    db.close();
                }

            }catch(Exception e){
                Log.e("MyHttpUtil.sendGetRequest()", e.getMessage());
            }finally {
                try{
                    if(pw!=null)pw.close();
                    if(isr!=null)isr.close();
                    if(br!=null)br.close();
                    if(conn!=null)conn.disconnect();
                }catch(Exception e){}
            }
            //응답받은 문자열을 리턴한다.
            return builder.toString();
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            //RequestListener 객체에(액티비티 or 서비스 or 프레그먼트 .. ) 넣어주기
            listener.onSuccess(requestId, s);
        }
    }
}

 

 

- doInBackground 안에 메소드 추가해주기

 

if(param!=null){//요청 파리미터가 존재 한다면
    //서버에 전송할 데이터를 문자열로 구성하기
    StringBuffer buffer=new StringBuffer();
    //Map에 존재하는 key값을 Set에 담아오기
    Set<String> keySet=param.keySet();
    Iterator<String> it=keySet.iterator();
    boolean isFirst=true;
    //반복문 돌면서 map 에 담긴 모든 요소를 전송할수 있도록 구성한다.
    while(it.hasNext()){
        String key=it.next();
        String arg=null;
        //파라미터가 한글일 경우 깨지지 않도록 하기 위해.
        String encodedValue=null;
        try {
            encodedValue= URLEncoder.encode(param.get(key), "utf-8");
        } catch (UnsupportedEncodingException e) {}
        if(isFirst){
            arg="?"+key+"="+encodedValue;
            isFirst=false;
        }else{
            arg="&"+key+"="+encodedValue;
        }
        buffer.append(arg);
    }
    String data=buffer.toString();
    //GET 방식 요청 파라미터를 요청 url 뒤에 연결한다.
    requestUrl +=data;
}

 

 

- Set 메소드를 사용해서 키값을 담아준다.

 

 

- Set순서가 없는 배열이라고 생각하면된다. 하나의 묶음이다!!

- num=1 name=kim addr=seoul 이 있다고 하면, num, name, addr이라는 키값만 keySet에 들어있는 것이다.

 

- keySet() 메소드로 맵의 키값만 호출하여 Iterator 를 사용해 일렬로 세워서 하나씩 빼낸다.

- 이후 Map 에 넣어서 목록으로 만든다.

 

 

- Map에 들어있는 내용을 가지고 쿼리 문자열을 만드는 것이 목적이다!!

- URL 경로 뒤에 붙이기 위해!

 

 

- 이렇게 쭉 연결해서 buffer를 사용해 나열해서 하나의 문자열을 얻어낸다.

 

 

- keySet에 들어있는 내용을 Map으로 문자열 만들기 => 문자열을 Url 뒤에 붙여서 경로 구성하기

- 이 요청 URL을 뒤에 붙여서 경로를 만들어 내는 것이 목적!

 

 

 

- 위에서 만든 URL경로를 받아와서 HttpUrlConnection 객체에 넣어서 원하는 작업을 한다.

 

 

rawQuery()

- sql문 문자열과 selection 인자를 받는다.

- cursor의 리턴타입은 cursor이다. JDBC의 resultSet과 같은 역할을 한다고 보면 된다.

 

 

moveToNext() 

- 쿠키 칼럼에서 커서를 한칸씩 내리면서 읽는다고 보면 된다.

- 아래에 내용이 있으면 true를 반환하면서 커서가 하나씩 내려온다.

 

 

- 이 쿠키를 while문으로 0번 인덱스에서부터 읽어와서 add한다.

 

- 응답코드가 200번이면 출력하는 문자열을 쭉 읽어낸다. if문으로 분기!

 

 

- 웹사이트 소스 보기에서 나오는 것처럼 이런 내용을 반복문으로 읽어서 누적시키는 것이다.

(안드로이드에서 받아오는 데이터는 http 가 아니라 JSON이지만!)

 

 

 

- if~else로 코드에 따라 결과 응답을 분기해준다. 300번대, 400번대, 500번대일 경우

- 아래 catch 문에서 exception을 발생시켜준다.

 

 

- onPostExecute로 이 누적된 String이 들어온다.

- 응답된 것을 여기에 넣어준다!

 

 

- 하지만 문자열 말고 쿠키도 같이 응답된다. 이 쿠키에 대한 처리도 필요!!

 

 

- 이미 존재하는 쿠키 키값이 있으면 수정해야 하고, 없으면 새 쿠키정보를 insert해야 한다.

- 쿠키값은 xxx=xxx 으로 되어있다. = 으로 구분되어 있다. 앞에 있는 것이 쿠키의 이름, 뒤에 있는 것이 쿠키 전체!

 

String cookie_name=cookie.split("=")[0];

 

- split을 사용해 = 으로 분리해서 0번 방에 있는것이 쿠키의 이름이라는 뜻.

 

 

- 이 문자열을 이 쿼리문의 ? 에 바인딩시킨다.

 

 

- select된 Row 의 개수가 없으면(0이면) insert, 있으면 update를 하도록 작성하면 된다.

 

 

- 현재 바인딩할 인자가 2개 있는데, sql문과 execSQL 메소드의 인자를 object[ ] 배열로 바인딩할 내용을 넣을 수 있다.

 

 

- 이렇게 SQL문 위에 미리 오브젝트 배열을 하나 만들어주고

 안에 들어갈 값을 0번방, 1번방에 각각 넣어주 면된다. ?에 순서대로 바인딩 될 수 있도록!

 

- 반드시 마지막에 db.close() 를 해야먄 반영된다.

 

- 이것으로 MyHttpUtil 은 일단 완성!

 


 

- Activity에서 MyHttpUtil 테스트해보기

 

new LoginCheckTask().execute(AppConstants.BASE_URL+"/music/logincheck");

 

- DetailActivity의 onStart()  로그인체크를 대체해보기!

 

 

- 액티비티에서 리스너를 구현, 추상메소드 오버라이드 한다.

 

 

- 그러면 new MyHttpUtil() 이렇게만 작성해도 아래의 로그인 코드 작업을 대체할 수 있게 된다.

 

 

- html이 응답된 것을 확인할 수 있다.

 

 

- 그러면 이제 각각의 Activity에서 pref, sessionId 등을 관리할 필요 없이 저 유틸리티만으로 처리할 수 있다.

 


 

- 이제 POST방식으로 요청하는 메소드를 만들어서 대체해 볼 것이다.

 

 

 

- LoginActivity의 LoginTask에서 보면 POST방식의 요청이 조금 다르다. 참고해서 수정해보기

 

 

- GetRequestTask 클래스를 복사해서 이름만 Post로 바꿔주기

 

 

- buffer에 문자열이 누적되게만 해두고, 파라미터 String 붙이는 코드는 지우기

 

- StringBuffer를 클래스에 변수로 선언해준다.

- StringBuffer 와 StringBuilder는 거의 비슷한 기능의 객체. StringBuilder가 좀 더 최신 버전이다.

 

- POST방식은 URL이 아니라 몸통(Body)에 전송되는 정보를 달고 간다.

 

 

- printWriter를 하나 선언해주고,

 

 

- Post 방식 파라미터를 달고 갈 수 있도록 코딩

- 쿼리 문자열을 서버에다가 printWriter 를 사용해서 직접 출력하고 있다.

 

- connection으로 String 객체를 얻어내서 직접 출력한다.

 

 

- 하단 try문에서 pw도 닫아준다.

 

 

 

- sendGetRequest 도 Post로 수정해서만들어주기

 

 


 

- 로그인액티비티 수정

 

LoginActivity

package com.example.step25imagecapture;

import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;

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

import com.example.step25imagecapture.databinding.ActivityLoginBinding;
import com.example.step25imagecapture.util.MyHttpUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

public class LoginActivity extends AppCompatActivity implements MyHttpUtil.RequestListener{
    ActivityLoginBinding binding;
    String id; //로그인 성공시 로그인된 아이디를 저장할 필드
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //화면 구성하기
        binding=ActivityLoginBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        binding.loginBtn.setOnClickListener(v->{
            //입력한 아이디 비밀번호를 읽어와서
            String id=binding.inputId.getText().toString();
            String pwd=binding.inputPwd.getText().toString();
            //Map 에 담는다.
            Map<String, String> map=new HashMap<>();
            map.put("id", id);
            map.put("pwd", pwd);

            new MyHttpUtil(this).sendPostRequest(1,
                    AppConstants.BASE_URL+"/music/login", map, this);
        });
        binding.resetBtn.setOnClickListener(v->{
            binding.inputId.setText("");
            binding.inputPwd.setText("");
        });
    }

    @Override
    public void onSuccess(int requestId, String data) {
        Log.d("data",data);
        boolean isSuccess=false;
        try{
            //data는 {"isSuccess":true} or {"isSuccess":false} 형식의 문자열이다.
            JSONObject obj=new JSONObject(data);
            //로그인 성공여부 얻어내기
            isSuccess=obj.getBoolean("isSuccess");
            if(isSuccess){
                id=obj.getString("id");
            }
        }catch (JSONException je){
            Log.e("onSuccess()", je.getMessage());
        }

        if(isSuccess){
            new AlertDialog.Builder(LoginActivity.this)
                    .setTitle("알림")
                    .setMessage(id+" 님 로그인 되었습니다.")
                    .setNeutralButton("확인", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            finish();//액티비티 종료
                        }
                    })
                    .create()
                    .show();
        }else{
            new AlertDialog.Builder(LoginActivity.this)
                    .setTitle("알림")
                    .setMessage("아이디 혹은 비밀 번호가 틀려요")
                    .setNeutralButton("확인", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            binding.inputId.setText("");
                            binding.inputPwd.setText("");
                        }
                    })
                    .create()
                    .show();
        }
    }

    @Override
    public void onFail(int requestId, Map<String, Object> result) {

    }
}

 

 

- LoginCheckTask를 Util을 사용하는 구조로 바꾸기

 

 

- Activity에 RequestListener를 구현한다.

 

 

- onCreate() 안에서 new MyHttpUtil() 로 실행해주고 인자를 넣어준다.

- 메소드를 오버라이드하면 결과 json문자열이 오버라이드한 메소드 onSuccess()로 들어온다.

 

 

- 성공하면 object에 id 값을 담아준다.

 

 

- 실행해보니 오류가 나서 MyHttpUtil의 sendPostRequest에서 일부수정...

(get방식이 아니므로 경로에 넣는 arg에 ? 들어가지 않도록 바꾸어주기)

 

 

- 이렇게 하면 UploadTask (파일업로드) 이외에는 모두 MyHttpUtil을 사용하는 구조로 바꿀 수 있다!