마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

로그인 구현 에러는 없는데 실행이 안되요

0 추천

회원가입은 잘되는데 로그인을 하면 id, pw가 맞아도 로그인실패가 됩니다..

login.java

public class login extends AppCompatActivity {
    String urlPath = "http://서버ip/LoginDB.php";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);getSystemService(Context.INPUT_METHOD_SERVICE);
        EditText emailEdit = findViewById(R.id.email);
        EditText pwdEdit = findViewById(R.id.pw);
        Button login = findViewById(R.id.login);
        login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AlertDialog.Builder builder = new AlertDialog.Builder(com.jinhee.login.login.this);
                String m_email = emailEdit.getText().toString();
                String m_pw = pwdEdit.getText().toString();
                if (m_email.equals("") || m_pw.equals("")) {
                    builder.setTitle("알림창").setMessage("데이터를 입력해주세요");
                    builder.setPositiveButton("확인", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    });
                    AlertDialog alertDialog = builder.create();
                    alertDialog.show();
                } else {
                    String checkid =null, checkpwd = null;
                    try {
                        loginTask task = new loginTask(login.this, urlPath);
                        task.execute(m_email, m_pw);
                        String callBackValue = task.get();
                        if(callBackValue.equals("error")|| callBackValue.equals("pwerr")){
                            builder.setTitle("로그인 실패");
                            if (callBackValue.equals("pwerr")) builder.setMessage("password가 오류입니다.");
                             else
                                builder.setMessage("해당 ID가 존재하지 않습니다.");
                            builder.setPositiveButton("확인", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                }
                            });
                        }else{
                        try {
                            JSONObject jsonObject = new JSONObject(callBackValue);
                            JSONArray jsonArray = jsonObject.getJSONArray("member");
                            for (int i = 0; i < jsonArray.length(); i++) {
                                JSONObject item = jsonArray.getJSONObject(i);
                                checkid = item.getString("m_email");
                                checkpwd = item.getString("m_pw");
                                String name = item.getString("m_name");
                            }
                        } catch (JSONException e) {
                            e.getMessage();
                        }
                        builder.setTitle("로그인 성공").setMessage(m_email + "님 메인페이지로 이동합니다.");
                        builder.setPositiveButton("확인", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Intent intent = new Intent(login.this, first.class);
                                startActivity(intent);
                            }
                        });
                         }
                        AlertDialog alertDialog = builder.create();
                        alertDialog.show();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        Button register = findViewById(R.id.register1);
        register.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(login.this, RegisterActivity.class);
                startActivity(intent);
            }
        });
    }
}

loginTask.java

public class loginTask extends AsyncTask<String, Void, String> {
    String urlPath;
    Context context;

    public loginTask(login login, String urlPath) {
        this.urlPath = urlPath;
    }
    @Override
    protected String doInBackground(String... params) {
        String postParameters = "m_email" + params[0] + "$m_pw=" + params[1];
        try {
            URL url = new URL(urlPath);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setReadTimeout(5000);
            httpURLConnection.setConnectTimeout(5000);
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.connect();
            OutputStream outputStream = httpURLConnection.getOutputStream();
            outputStream.write(postParameters.getBytes("UTF-8"));
            outputStream.flush();
            outputStream.close();
            InputStream inputStream;
            if (httpURLConnection.getResponseCode() ==
                    HttpURLConnection.HTTP_OK) {
                inputStream = httpURLConnection.getInputStream();
            } else {
                inputStream = httpURLConnection.getErrorStream();
            }
            InputStreamReader Reader =
                    new InputStreamReader(inputStream, "UTF-8");
            BufferedReader bufferedReader = new BufferedReader(Reader);
            StringBuilder builder = new StringBuilder();
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                builder.append(line);
            }
            bufferedReader.close();
            return builder.toString();

        } catch (Exception e) {
            return "error";
        } }}

LoginDB.php

<?php
header('content-type: text/html; charset=utf-8');
$db = mysqli_connect("ip","user","pw","db");
if(!$db){
die("Error ".mysqli_connect_error());
}

mysqli_set_charset($db, 'UTF8');

$m_email = $_POST['m_email'];
$m_pw = $_POST['m_pw'];

$result_arr = array();
$result = $db->query("SELECT * FROM user WHERE m_email='$m_email' AND m_pw = '$m_pw'");
$num = $result->num_rows;
if($num > 0) {
$low = $result->fetch_assoc(); 
array_push($result_arr,$low);
header('Content-Type: application/json; charset=utf8');  
echo json_encode(array("member"=>$result_arr));
}else{
$test = $db->query("SELECT * FROM user WHERE m_email='$m_email'");
$cnt = $test->num_rows; 
if($cnt > 0)
echo 'pwerr';  
else
echo 'error';
}
mysqli_close($db);
?>

답변부탁드립니다...!

jinihelpp111 (190 포인트) 님이 2021년 10월 29일 질문
구체적으로 어느 부분에서 에러가 나는지 확인해 보세요. 서버 API가 호출은 되는지, 응답값을 제대로 받는지, JSON을 파싱하다가 에러는 나지 않는지. JSON파싱은 제대로 했는데 데이터 비교를 잘못한 것인지.

질문에는 벗어난 이야기인데, 코드를 일기 쉽게 정리를 하셔야 할 것 같네요. 모든 코드를 한 곳에 몰아 넣어서 보기가 쉽지 않네요. 그리고 AsyncTask는 deprecated가 되어서 Retrofit같은 라이브러리로 대체하시는게 좋구요, AsyncTask.get()은 blocking이라 UI를 버벅거리게 만들 수 있기 때문에 사용하지 않으셔야 해요. 대신 콜백을 사용하시는게 훨씬 좋아요.
넵 감사합니다!!

제가 초보라서 그런데 혹시 어느부분에서 에러가 나는지는 어떻게 찾을 수 있나요..?

안드로이드스튜디오 Logcat - Debug에서는 오류가 나지 않았습니다..
응답은 정상적으로 받아지는 거네요. 응답값이 에러인지 비교하는 부분과  JSON파싱하는 부분을 확인해 보셔야 겠는데요. 값을 확인할 필요가 있는 곳에 브레이크 포인트를 걸고 디버그모드를 사용하세요. 디버거 사용의 자세한 방법은 제 긴 설명보다는 구글에서 찾아보세요.

1개의 답변

0 추천

제가 보는 관점에서 코드를 역할에 맞게 클래스별로 쪼개서 정리해 봤습니다. 완벽한 코드는 아니니 이런 식으로 만들 수 있다는 가이드로 여기시면 좋을 것 같습니다.

눈여겨 보실 것은 LoginActivity 와 LoginTask는 LoginTask.Listener 인터페이스를 통해서 데이터를 주고 받도록 변경하였습니다. 이렇게 함으로써 두 클래스사이의 종속성이 줄어들고 LoginTask는 좀 더 재사용이 쉬워지게 됩니다.

public class UiError {
   private final String title;
   private final String message;
   public UiError(title: String, message: String) {
         this.title = title;
         this.message = message;
   }

  public String getTitle() { return title; }
  public String getMessage() { return message; }
}

public class LoginActivity extends AppCompatActivity implements LoginTask.Listener {
    private EditText emailEdit;
    private EditText pwdEdit;
 
   private String getEmail() { return emailEdit.getText().toString().trim(); }
   private String getPassword() { return pwdEdit.getText().toString().trim(); }

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

        emailEdit = findViewById(R.id.email);
        pwdEdit = findViewById(R.id.pw);

        Button login = findViewById(R.id.login);
        login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                 login();            
           }
        );

        Button register = findViewById(R.id.register1);
        register.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(login.this, RegisterActivity.class);
                startActivity(intent);
            }
        });
    }

   private void login() {
          UiError uiError = validateLoginInput();
          if (uiError != null) {
              showUiError(uiError);
              return;
          }  
           
         peformLoginRequest();
   }

   @Nullable
   private UiError validateLoginInput() {
         if ("".equals(getEmail()) || "".equals(getPassword())) {
             return UiError("알림창", "데이터를 입력해주세요");
         }

         return null;
   }

   private void showUiError(UiError uiError) {
           showError(uiError.getTitle(), uiError.getMessage);
   }

   private void showError(String title, String message) [
         AlertDialog.Builder builder = new AlertDialog.Builder(this);
          AlertDialog alertDialog = builder.setTitle(title)
                     .setMessage(message);
                     .setPositiveButton("확인")
                     .create();
          alertDialog.show();
   }

   private void peformLoginRequest() {
          LoginTask task = new LoginTask(this); 
          task.setLoginInput(getEmail(), getPassword());
          task.execute();
   }

  @Overrid
  public void loginFailureWithError(LoginError error) {
           switch (error) {
               case HTTP_ERROR:  
                       showError("로그인 실패", "메세지");
                       break;
               case INVALID_USER:  
                       showError("로그인 실패", "메세지");
                       break;
               case JSON_PARSE_ERROR:  
                       showError("로그인 실패", "메세지");
                       break;
               case MISC_ERROR:  
                       showError("로그인 실패", "메세지");
                       break;
           }
  }       

 @Overrid
  public loginSucceeded(List<Memeber> members){
        Intent intent = new Intent(login.this, first.class);
        startActivity(intent);
  } 
}

 

LoginTask입니다. 사용자에게 로그인 에러메세지를 보여줄 때 아이디가 틀렸는지, 패스워드가 잘못되었는지 구체적으로 알려주시는 것은 보안을 허술하게 만들 수 있습니다. 일반적인 메세지만 보여주어야 합니다.

public enum LoginError {
    HTTP_ERROR, INVALID_USER, JSON_PARSE_ERROR, MISC_ERROR
}

public class LoginResult {
    @Nullable private final LoginError error;
    private final List<Memeber> members;

    private LoginResult(@Nullable LoginError error, List<Member> members) {
        this.error = error;
        this.members = members;
    }
   
    public static LoginResult error(LoginError error) {
          return new LoginResult(error, new ArrayList<>());
    }

    public static LoginResult success(List<Member> members) {
         return new LoginResult(null, members);
    }

    public boolean isError() {
        return error != null;
    }
}

public class Memeber {
   private final String email;
   private final String name;
   // 생성자, getters & setters생략
}


public class loginTask extends AsyncTask<Void, Void, LoginResult> {
    private static final String LOGIN_ENDPOINT = "http://서버ip/LoginDB.php";

    interface Listener {
         void loginFailureWithError(LoginError error);
         void loginSucceeded(List<Memeber> members);
    }
    
    private String email, password;
    private Listener lisetner;

    public loginTask(@NotNull Listener lisetner) {
        this.listener = listener;
    }
    
   public void setLoginInput(String email, String password) {
       this.email = email;
       this.password = password;
   }

    @Override
    protected String doInBackground(String... params) {
        try {
            String responseString = HttpRequestUtil.post(LOGIN_ENDPOINT, getPostParameters());
            if ("error".equals(responseString) || "pwerr".equals(responseString)) {
                 return LoginResult.error(LoginErrorType.INVALID_USER);
            }

            return parseJSON(responseString);
       
        } catch (IOException e) {
            return LoginResult.error(LoginErrorType.HTTP_ERROR);
        } catch (JSONException e) {
            return LoginResult.error(LoginErrorType.JSON_PARSE_ERROR);
        } catch (Exception e) {
            return LoginResult.error(LoginErrorType.MISC_ERROR);
        } 
    }

    private String getPostParameters() {
        return  "m_email" + email + "$m_pw=" + password;
    }

    private LoginResult parseJSON(String json) {
          List<Member> members = new ArrayList<>();

         JSONObject jsonObject = new JSONObject(callBackValue);
         JSONArray jsonArray = jsonObject.getJSONArray("member");
         for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject item = jsonArray.getJSONObject(i);
                checkid = item.getString("m_email");
                checkpwd = item.getString("m_pw");
                String name = item.getString("m_name");
                members.add(new Member(checkid, name));
          }
         
         return LoginResult.success(members);
    }
    
   @Override
   protected void onPostExecute (LoginResult loginResult) {
         if (loginResult.isError()) {
              listener.loginFailureWithError(loginResult.getError());
              return;
        }

        listener.loginSucceeded(loginResult.getMembers());
   }
}

public class HttpRequestUtil {
    public static String post(String urlString, String postParameters) {
        URL url = new URL(urlString);
        // 생략
        return bufferedReader.close();
    }
}

 

HttpRequest를 하는 부분은 Readability를 위하여 별도의 유틸클래스로 분리했습니다. 일단 http 핸들링에 익숙해지시면 Retrofit같은 라이브러리를 사용하셔서 보일러플레이트 코드를 줄이시기 바랍니다.

 

spark (227,470 포인트) 님이 2021년 10월 29일 답변
spark님이 2021년 10월 29일 수정
감사합니다! 가이드 주신대로 열심히 해봤는데 제 실력으로는 잘 안되네요..ㅠ
다른 프로그램에서도 같은 에러가 나는지 체크해 보세요. Postman 같은 걸 이용하면 좋을 것 같고, 거기에서도 똑 같은 에러가 난다면 서버쪽 문제이겠고 안드로이드 앱만 그렇다면, 앱의 코드 문제이겠죠.
...