Client/Android

Android - JSON 파싱 예제

JaeHoney 2020. 8. 13. 10:39

개요

이전 포스트에서는 Rest API와 GET방식과 POST방식의 통신에 대해 알아봤습니다. 이번에는 AsyncTask를 활용해 API에서 필요한 값만 변수로 가져오는 예제를 해보겠습니다. 방식은 전과 같이 로그인을 위한 API에 값을 전송한 뒤, 결과 중 code값을 받아 해당 code값에 맞는 메시지를 토스트 처리하도록 코드를 구성하겠습니다.

 

activity_login.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".login"
    android:orientation="vertical"
    android:gravity="center_vertical">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/edit_login_email"/>
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/edit_login_pwd"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnLogin"
        android:text="로그인"/>
</LinearLayout>

 

위처럼 id(email)을 입력할 EditText 한 개, 비밀번호를 입력할 EditText 한 개, 로그인 버튼 한 개를 레이아웃에 넣고 버튼을 누르면 API서버에 EditText의 값들을 서버로 전송하고 결과값을 받아올 것입니다.

 

OnCreate()에서 API 호출

 

public class login extends AppCompatActivity {

    EditText editEmail,editPwd;

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

        
        final Button btnLogin = (Button) findViewById(R.id.btnLogin);
        editEmail = (EditText) findViewById(R.id.edit_login_email);
        editPwd = (EditText) findViewById(R.id.edit_login_pwd);

        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String idEdit = editEmail.getText().toString();
                String pwdEdit = editPwd.getText().toString();
                new RestAPITaskLogin("http://XXX.XXX.XXX.XXX/api/index.php/member/login_member", idEdit, pwdEdit).execute();

            }
        });
        
    }

 

EditText들의 값을 String 타입의 변수로 바꿔주고 값들을 이용해 POST방식으로 서버에 값을 전송하고 결과를 처리할 것입니다. 위처럼만 작성하고 AsyncTask클래스를 상속받는 내부클래스 RestAPITaskLogin를 작성할 것입니다. 

 

RestAPITaskLogin Class

 

public class RestAPITaskLogin extends AsyncTask<Integer, Void, String> {
        protected String mURL;
        protected String id, pwd;

        public RestAPITaskLogin(String url, String id, String pwd) {
            this.mURL = url;
            this.id = id;
            this.pwd = pwd;
        }

        @Override
        protected String doInBackground(Integer... params) {
            try {
                URL url = new URL(mURL);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setDefaultUseCaches(false);
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);
                conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
                conn.addRequestProperty("apikey", "XXXX");

                StringBuffer buffer = new StringBuffer();
                buffer.append("email").append("=").append(id).append("&");
                buffer.append("password").append("=").append(pwd);

                OutputStreamWriter outputStream = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
                PrintWriter writer = new PrintWriter(outputStream);
                writer.write(buffer.toString());
                System.out.println(buffer.toString());
                writer.flush();
                writer.close();

                InputStreamReader tmp = new InputStreamReader(conn.getInputStream(), "UTF-8");
                BufferedReader reader = new BufferedReader(tmp);
                StringBuilder builder = new StringBuilder();
                String str;
                while ((str = reader.readLine()) != null) {
                    builder.append(str + "\n");
                }
                String result = builder.toString();
                JSONObject jsonObject = new JSONObject(result);
                JSONObject postObject = jsonObject.getJSONObject("code");
                String code = postObject.getString("code");

                return code;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;

        }

        @Override
        protected void onPostExecute(String code) {

            if (code.equals("207")) {
                Toast.makeText(getApplicationContext(), "로그인 실패", Toast.LENGTH_SHORT).show();
            } else if (code.equals("200")) {
                Toast.makeText(getApplicationContext(), "로그인 성공", Toast.LENGTH_SHORT).show();
                Intent intent = new Intent(getApplicationContext(), main.class);
                startActivity(intent);

            } else if (code.equals("206")) {
                Toast.makeText(getApplicationContext(), "API Key가 틀렸습니다.", Toast.LENGTH_SHORT).show();
            } else if (code.equals("500")) {
                Toast.makeText(getApplicationContext(), "API 실행 중 시스템에서 발생한 에러입니다.", Toast.LENGTH_SHORT).show();
            }

        }
    }

 

AsyncTask클래스를 상속받고 doInBackground()메서드와 onPostExecute() 메서드를 오버라이딩 합니다. AsyncTask의 리스트 중 첫번째는 doInBackgorund()메서드의 파라미터 타입이고 세번째는 onPostExecute()메서드의 파라미터 타입입니다. 생성자에는 id값과 password값을 받아서 서버에 요청해야 하므로 URL까지 String 타입 변수 3개를 받아야 합니다. doInBackground()메서드 안에 있는 StringBuffer에 append()메서드로 보낼 값들을 연결해 전송하고  JSONObject 클래스를 통해 원하는 값을 파싱해 불러온 뒤 return 하면 onPostExecute() 메서드에서 인자로 받아와서 결과값에 맞게 처리합니다. 예제에서는 토스트를 출력한 뒤 메인 화면으로 이동하게 작성하였습니다.

 

테스트

 

DB에 테스트용 계정으로 test@test.com/1234를 넣었습니다. 이 계정을 이용해 위 예제를 테스트 해보겠습니다.

 

password를 "1234"를 입력해야 하는데 "1234X"를 입력하니까 로그인 실패라는 토스트가 나옵니다

.

 

올바르게 입력하니 로그인 성공이라는 토스트와 함께 다음 화면으로 넘어가는 모습입니다. 이를 이용해 서버에 값을 보내고 결과값들을 원하는 방식으로 사용하면 됩니다.