[Android Studio] 안드로이드에서 로그인 기능 구현하기 [1]

         


안녕하세요~ 

요즘에 진행하는 프로젝트에서 회원가입/로그인 기능을 넣으려고 하는데, 가장 많이 쓰이는 기능임에도 따로 정리한 포스팅이 없어서 이번에 작성하려고 합니다. 


만들고자 하는 기능은 다음과 같습니다.


- 안드로이드에서 ID(이메일주소), PASSWORD를 입력하여 회원가입

- 입력된 ID와 PASSWORD를 DB에 저장하고 이메일 인증메일 발송

- 인증메일에 포함된 특정 URL클릭시 회원가입 완료

- 안드로이드에서 ID와 PASSWORD를 통해 로그인


기본적인 로그인과 다른점이라면 '이메일 인증'이 추가된 겁니다. 아마 회원가입을 하다보면 이메일로 인증메일이 발송되고 이메일 안에 어떤 URL을 클릭해야 회원가입이 되는 것을 몇번 경험해 본적이 있을겁니다. 이는 주민등록번호와 같은 개인정보를 수집하지 않는 사이트에서 본인인증방법으로 많이 쓰는 방법이에요. 저같은 경우는 회사 EMAIL을 ID로 사용하기 때문에 진짜 회사 EMAIL을 가지고 있는지 검증하기 위해 이메일 인증 기능을 적용하려고 합니다.


포스팅은 기본적인 기능들(안드로이드의 기본적인 메소드 사용법 등)에 관한 자세한 설명은 생략하고 어느정도 알고 있다는 가정하에 기능 위주의 설명을 해드리며 진행하도록 하겠습니다. 일단 가장 먼저 안드로이드 화면에서 ID와 PASSWORD를 입력받는 기능을 만들어야 겠지요? 저는 일단 아래처럼 만들었습니다.



매우 심플하지요? ㅎㅎ

추가적인 요소들을 많이 써야 하지만 일단 기능 구현이 우선이기 때문에 ID와 PASSWORD를 입력하고 PASSWORD를 한번 더 입력하는 화면을 만들어 보았습니다. 마지막으로 회원가입버튼을 하나 추가했구요. 화면을 위와같이 구성했다면 우리는 3개의 에디트텍스트 객체를 통해 입력값을 받을 수 있습니다.


public class JoinActivity extends AppCompatActivity {

EditText et_id, et_pw, et_pw_chk;
String sId, sPw, sPw_chk;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_join);

et_id = (EditText) findViewById(R.id.et_Id);
et_pw = (EditText) findViewById(R.id.et_Password);
et_pw_chk = (EditText) findViewById(R.id.et_Password_chk);

sId = et_id.getText().toString();
sPw = et_pw.getText().toString();
sPw_chk = et_pw_chk.getText().toString();


위 코드를 보시면 3개의 에디트텍스트에서 각각 입력된 텍스트값을 가져와서 String 변수에 넣는 것을 확인 할 수 있습니다. 근데 onCreate() 선언했기 때문에 화면이 뜨자마자 입력된 값을 불러오게 되는데, 화면이 뜨는 순간은 아무것도 입력된게 없겠지요? 아까 만들었던 Join버튼을 눌렀을때 값들을 불러와야 하기 때문에 버튼을 눌렀을 때 동작하도록 바꾸겠습니다.


클릭 이벤트는 안드로이드 프로그래밍이 발전하면서 상당히 여러가지 방법으로 구현이 가능한데요, 제가 자주 사용하는 방법은 레이아웃에서 onClick을 이용한 방법입니다. 


<Button
android:text="Join"
android:layout_width="100dp"
android:layout_height="48dp"
android:id="@+id/bt_Join"
android:clickable="true"
android:onClick="bt_Join"
android:textAlignment="center"
app:layout_constraintLeft_toLeftOf="@+id/activity_join"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="@+id/et_Password_chk"
android:layout_marginTop="32dp"
app:layout_constraintRight_toRightOf="@+id/activity_join"
android:layout_marginEnd="16dp"
tools:ignore="HardcodedText" />

위와같이 레이아웃에 버튼객체에 android:onClick과 android:clickable 어트리뷰트를 추가합니다. clickable은 클릭을 가능하게 해주며, onClick의 경우 클릭했을 때 동작하는 메소드 이름을 정의합니다. 저는 bt_Join으로 이름지었어요. bt는 버튼을 줄인것입니다.(제맘대로.. ^^)


레이아웃 XML에서 위와같이 선언할 경우 해당하는 액티비티 소스에서 다음과 같이 메소드를 선언할 수 있습니다.


public class JoinActivity extends AppCompatActivity {

EditText et_id, et_pw, et_pw_chk;
String sId, sPw, sPw_chk;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_join);

et_id = (EditText) findViewById(R.id.et_Id);
et_pw = (EditText) findViewById(R.id.et_Password);
et_pw_chk = (EditText) findViewById(R.id.et_Password_chk);
}

/* onClick에서 정의한 이름과 똑같은 이름으로 생성 */
public void bt_Join(View view)
{
/* 버튼을 눌렀을 때 동작하는 소스 */
sId = et_id.getText().toString();
sPw = et_pw.getText().toString();
sPw_chk = et_pw_chk.getText().toString();
}

이제 Join버튼을 클릭할 때 에디트 텍스트에서 텍스트값을 불러오게 됩니다. 이 값들을 DB에 넣어야 하는데 넣기전에 비밀번호확인을 제대로 입력했는지 체크하는 것을 넣도록 하겠습니다.


/* onClick에서 정의한 이름과 똑같은 이름으로 생성 */
public void bt_Join(View view)
{
/* 버튼을 눌렀을 때 동작하는 소스 */
sId = et_id.getText().toString();
sPw = et_pw.getText().toString();
sPw_chk = et_pw_chk.getText().toString();

if(sPw.equals(sPw_chk))
{
/* 패스워드 확인이 정상적으로 됨 */

}
else
{
/* 패스워드 확인이 불일치 함 */

}
}

equals 메소드를 통해 입력된 PASSWORD와 CHK가 같은 값인지 확인하고 다를 경우 에러를 리턴하도록 만들고, 같으면 서버에 보내면 됩니다.


이제 서버로 값들을 전송하는 것을 만들 것인데.. 안드로이드에서 바로 DB로 넣지는 못하고 서버를 중계해서 DB로 넣도록 하겠습니다. 안드로이드 -> PHP -> MySql형태로 만들 것인데 이 부분에 내용은 해당 포스팅을 참고하시면 됩니다.


PHP를 이용해 MySql 연동하기


JSP를 이용해 MySql 연동하기


여기서는 PHP를 통해 서버와 연동시킬 계획입니다. 안드로이드에서는 4.0부터 서버와 통신할 때 쓰레드 사용을 권장하고 있습니다. 여기서는  AsynkTask를 통해 서버에 데이터를 전송해보도록 하겠습니다. 그러기 위해선 먼저 서버에서 데이터를 받는 프로그램을 만들어야 겠네요.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
snclib_join.php 
 <?
    header('content-type: text/html; charset=utf-8'); 
 
    // 데이터베이스 접속 문자열. (db위치, 유저 이름, 비밀번호)
    $connect=mysql_connect"db주소""로그인ID""로그인PW") or  
        die( "SQL server에 연결할 수 없습니다.");
    
    mysql_query("SET NAMES UTF8");
   // 데이터베이스 선택
   mysql_select_db("DB이름",$connect);
 
   // 세션 시작
   session_start();
 
 
 
   $id = $_REQUEST[u_id];
   $pw = $_REQUEST[u_pw]; 
   $sql = "INSERT INTO USERS(USERID, PASSWORD) VALUES('$id', '$pw')";
 
   $result = mysql_query($sql);
 
   if(!$result)
            die("mysql query error");
    else 
        echo("DB 입력 성공");
?>
cs


위는 GET방식을 사용하여 안드로이드로부터 입력받은 ID와 PW를 DB에 입력하는 PHP코드입니다. 이런 개인적인 프로젝트에서는 ID, PW를 GET방식으로 받아도 상관없는데, 서비스하는 프로그램일 경우 GET방식으로 ID나 PW를 받으면 상당히 위험합니다. URL에 전송되는 값들이 노출되기 때문이죠. 한번 POST형태로 바꿔볼까요?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
snclib_join.php 
<?
    header('content-type: text/html; charset=utf-8'); 
    // 데이터베이스 접속 문자열. (db위치, 유저 이름, 비밀번호)
    $connect=mysql_connect"db주소""로그인ID""로그인PW") or  
        die( "SQL server에 연결할 수 없습니다.");
    
    mysql_query("SET NAMES UTF8");
   // 데이터베이스 선택
   mysql_select_db("DB이름",$connect);
 
   // 세션 시작
   session_start();
 
   $id = $_POST[u_id];
   $pw = $_POST[u_pw]; 
 
   $sql = "INSERT INTO USERS(USERID, PASSWORD) VALUES('$id', '$pw')";
 
   $result = mysql_query($sql);
 
   if(!$result)
            die("mysql query error");
   else
        echo "insert success"
 
?>
cs


네~ 사실 데이터를 받는 쪽에서는 별로 수정할 것이 없습니다. ㅎㅎ 주는 쪽에서는 많이 수정해야 하지요. 이제 안드로이드에서 어떻게 서버에 데이터를 전송하는지 볼까요?



public class registDB extends AsyncTask<Void, Integer, Void> {

@Override
protected Void doInBackground(Void... unused) {

/* 인풋 파라메터값 생성 */
String param = "u_id=" + sId + "&u_pw=" + sPw + "";
try {
/* 서버연결 */
URL url = new URL(
"http://서버주소/snclib_join.php");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.connect();

/* 안드로이드 -> 서버 파라메터값 전달 */
OutputStream outs = conn.getOutputStream();
outs.write(param.getBytes("UTF-8"));
outs.flush();
outs.close();

/* 서버 -> 안드로이드 파라메터값 전달 */
InputStream is = null;
BufferedReader in = null;
String data = "";

is = conn.getInputStream();
in = new BufferedReader(new InputStreamReader(is), 8 * 1024);
String line = null;
StringBuffer buff = new StringBuffer();
while ( ( line = in.readLine() ) != null )
{
buff.append(line + "\n");
}
data = buff.toString().trim();
Log.e("RECV DATA",data);

} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

return null;
}

}

앞서 말했듯이 서버에 접속할 때는 쓰레드가 필요합니다. 따라서 AsynkTask를 이용해서 서버에 접속하게되는데요, 자주 사용하는 메소드니 레퍼런스를 읽어보시는게 좋습니다. 여기서는 입력인자가 없는 AsynkTask를 만들었습니다. 서버주소는 현재 서버프로그램이 저장된 서버URL주소를 적으시면 되구요 snclib_join.php는 아까 만든 서버프로그램을 입력하시면 됩니다. 파라메터가 서버에 전달되는 것은 주석을 읽어보면 이해되실 겁니다. 사실 서버에서 클라이언트로 주는 값은 딱히 없지만 성공 실패 여부나 기타 로그를 찍기위해 만들었습니다. 


이제 Join버튼을 클릭했을때 이 메소드가 실행되게 해봅시다.


public void bt_Join(View view)
{
/* 버튼을 눌렀을 때 동작하는 소스 */
sId = et_id.getText().toString();
sPw = et_pw.getText().toString();
sPw_chk = et_pw_chk.getText().toString();

if(sPw.equals(sPw_chk))
{
/* 패스워드 확인이 정상적으로 됨 */
registDB rdb = new registDB();
rdb.execute();
}
else
{
/* 패스워드 확인이 불일치 함 */

}
}


위에서 만든 AsynkTask 클래스를 선언한뒤 execute()해주면 실행되게됩니다. 이제 안드로이드에서 ID와 PASSWORD를 입력하면 DB에 저장되게 됩니다. 테스트해볼까요?



테스트를 위해 testtest/testtest를 입력했을 때 모습입니다. DB에 정상적으로 입력된 것이 확인되는군요!.

이것으로 일단 ID와 PW를 입력받아 DB에 저장하는 기능을 구현했습니다!!


다음 포스팅에서는 로그인 구현 및 인증 이메일 전송을 구현하도록 하겠습니다.

댓글(47)

  • 이전 댓글 더보기
  • 개초보
    2017.06.01 17:25

    레지스트디비 클래스 작성하고 돌리려는데
    String param = "u_id=" + sId + "&u_pw=" + sPw + "";

    sId랑 sPw 부분이 can not symbol error 나네요

    registdb에서 어떻게 불러와야하죠??

    • 2017.06.01 17:28 신고

      sId와 sPw가 전역변수(코드 맨 위에 )로 선언되었나요 ?

    • 2017.06.01 17:29 신고

      참고로 registdb는 따로 클래스 파일 생성한게 아니라 JoinActivity 안에 클래스를 만든겁니당 ~

  • 개초보
    2017.06.01 17:33

    public class JoinActivity extends AppCompatActivity {

    String sId,sPw,sPw_chk;
    바로아래에선언했습니다..
    그리고 registdb도 JoinActivity아래에 작성했어요

    • 2017.06.01 17:34 신고

      아래 만드신건가요 안에 만드신건가요 ? ㅎㅎ

  • 개초보
    2017.06.01 17:34

    제가작성한코드인데 자바를 날로해먹어서그런지 문제가많네요;

    package com.example.bong.myapplication;

    import android.content.DialogInterface;
    import android.os.AsyncTask;
    import android.support.annotation.IdRes;
    import android.support.v7.app.AlertDialog;
    import android.support.v7.app.AppCompatActivity;
    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 java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;

    public class JoinActivity extends AppCompatActivity {

    String sId,sPw,sGd,sPw_chk;

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

    final EditText in_regid = (EditText)findViewById(R.id.in_regId);
    final EditText in_regpw = (EditText)findViewById(R.id.in_regpw);
    final EditText in_regpwchk = (EditText)findViewById(R.id.in_regpwchk);


    Button btn_reg = (Button)findViewById(R.id.btn_reg);
    final RadioGroup r_group = (RadioGroup)findViewById(R.id.r_group);
    RadioButton r_b_m = (RadioButton)findViewById(R.id.r_b_m);
    RadioButton r_b_f = (RadioButton)findViewById(R.id.r_b_f);










    btn_reg.setOnClickListener(new Button.OnClickListener(){
    String gender;
    @Override
    public void onClick(View v) {
    String sId= in_regid.getText().toString();
    String sPw= in_regpw.getText().toString();
    String sPwchk= in_regpwchk.getText().toString();
    String sGd= gender.toString();


    r_group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener(){
    @Override
    public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {

    if(checkedId==R.id.r_b_m) {
    gender="남자";
    }
    if(checkedId==R.id.r_b_f){
    gender="여자";
    }


    }
    });



    if(sPw.equals(sPwchk)&&sGd!=null){

    registDB rdb = new registDB();
    rdb.execute();

    }
    else{


    }
    }
    });

    }


    }
    public class registDB extends AsyncTask<Void, Integer, Void> {
    @Override
    protected Void doInBackground(Void... params) {


    String param = "u_id=" + sId + "&u_pw=" + sPw + "&u_gd="+sGd+"";
    try {
    /* 서버연결 */
    URL url = new URL(
    "http://localhost/join.php";);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded";);
    conn.setRequestMethod("POST";);
    conn.setDoInput(true);
    conn.connect();

    /* 안드로이드 -> 서버 파라메터값 전달 */
    OutputStream outs = conn.getOutputStream();
    outs.write(param.getBytes("UTF-8";));
    outs.flush();
    outs.close();

    /* 서버 -> 안드로이드 파라메터값 전달 */
    InputStream is = null;
    BufferedReader in = null;
    String data = "";

    is = conn.getInputStream();
    in = new BufferedReader(new InputStreamReader(is), 8 * 1024);
    String line = null;
    StringBuffer buff = new StringBuffer();
    while ( ( line = in.readLine() ) != null )
    {
    buff.append(line + "\n";);
    }
    data = buff.toString().trim();
    Log.e("RECV DATA",data);

    } catch (MalformedURLException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }


    return null;
    }
    }

  • 개초보
    2017.06.01 17:36

    저기 괜히 성별부분 라디오버튼 해보려다가 그런거같기도하고; 참 어렵네요

    • 2017.06.01 17:44 신고

      btn_reg.setOnClickListener(new Button.OnClickListener(){
      String gender;
      @Override
      public void onClick(View v) {
      String sId= in_regid.getText().toString();
      String sPw= in_regpw.getText().toString();
      String sPwchk= in_regpwchk.getText().toString();
      String sGd= gender.toString();

      요부분에서 String으로 또 선언을 하셨네용

      sId = in_reg..... 형태로 바꾸세요~

  • 개초보
    2017.06.01 17:40

    두인백그라운드는 그대로 카피하구 String param 부분에 성별부분만넣어봤구여 버튼이벤트는 리스너썼구요..

  • 개초보
    2017.06.01 17:47

    registDB를 액티비티 JoinActivity 안에 작성해야하나요 아니면 바깥에작성해야하나요

    일단 혼자해보겠습니다 ㅠ

  • 개초보
    2017.06.01 18:15

    정말 어처구니 없는 질문이 아닐수없는데 클래스안에 클래스가 선언되는걸 처음알았는데요.이게 이너클래스?그런건가요?
    어떤개념일까요.. 자꾸 이상한질문에 답해주셔서 감사합니다.

    • 2017.06.01 18:20 신고

      클래스도 사실 변수와 같아서 어디다 선언해도 똑같아요~ 밖에 쓰면 전역클래고 안에쓰면 내부 클래스

  • uki
    2017.06.22 09:59

    .php:
    $id = $_POST[u_id]

    이 부분에서 u_id는 어디에 정의된 변수인가요?

    joinActivity 를 보니깐, android:id 는 아닌거같은데ㅠ

    • 2017.06.22 10:40 신고

      안드로이드에서 서버에 보낼때

      /* 인풋 파라메터값 생성 */
      String param = "u_id=" + sId + "&u_pw=" + sPw + "";

      요렇게 만들자나요? 요기서 정의한답니다.

    • uki
      2017.06.22 16:39

      감사합니다 정말 :)

  • 카별
    2017.06.29 18:13

    안녕하세요,글 잘 읽었습니다.

    자바 파일은 URL url = new URL(http://hgjeon1993.cafe24.com/snclib_join.php";); 로 두고,

    php 파일은
    $connect=mysql_connect( "uws64-250.cafe24.com/WebMysql", "DB접속아이디", "DB접속비밀번호";) or
    die( "SQL server에 연결할 수 없습니다.";);
    mysql_select_db("hgjeon1993",$connect);

    로 두고 앱을 실행하였는데, 회원가입 버튼을 누르면 앱의 작동이 중지됩니다.

    혹시 왜 그런지 알려주시면 감사하겠습니다.

    • 2017.06.29 18:17 신고

      에러로그난 부분을 올려주시겠어요~?

  • 카별
    2017.06.29 18:51

    Process: com.hgjeon1993gmail.catholicdate, PID: 10025
    java.lang.IllegalStateException: Could not find method bt_join(View) in a parent or ancestor Context for android:onClick attribute defined on view class android.support.v7.widget.AppCompatButton with id 'joinbutton'
    at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.resolveMethod(AppCompatViewInflater.java:327)
    at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:284)
    at android.view.View.performClick(View.java:5637)
    at android.view.View$PerformClick.run(View.java:22429)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6119)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
    이렇게 나오네요

    • 2017.06.29 20:00 신고

      서버가 문제가 아니라 버튼을 눌럿을때 메소드 이름에 문제가 있나 보내요 bt_join 이라고 선언하셨나요?

  • 김규형
    2017.08.02 16:04

    안녕하세요 궁금한 점이 있는데요. snclib_join 파일에서 session_start(); 가 최 상단에 있지 않아도 실행이 되나요?

    • 2017.08.03 17:59 신고

      넵 session_start()위에부분은 실제로 클라이언트에 데이터를 사용하지 않는 부분(DB셋팅)이라 상관없습니다~!

  • OH
    2017.08.04 04:42

    안녕하세요 기존에 만들려는 프로젝트에 작성하신 것보고 참고해서 붙였는데
    mysqli query error가 출력되는 것을 보니 result가 die됬다는 것 같은데 이유를 알 수 있을까요?

  • 최동현
    2017.08.15 19:06

    package com.example.dongdong.login;

    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.Toast;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;


    public class Login extends AppCompatActivity {
    EditText et_id, et_pw,et_pw2;
    String sId, sPw, sPw2;

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

    et_id=(EditText) findViewById(R.id.et_id);
    et_pw=(EditText) findViewById(R.id.et_pw);
    et_pw2=(EditText) findViewById(R.id.et_pw2);
    }
    public void bt_join(View view)
    {
    sId=et_id.getText().toString();
    sPw=et_pw.getText().toString();
    sPw2=et_pw2.getText().toString();
    if(sPw.equals(sPw2))
    {
    Toast.makeText(getApplicationContext(), "일치합니다",Toast.LENGTH_SHORT).show();
    }else
    {
    Toast.makeText(getApplicationContext(), "불일치합니다",Toast.LENGTH_SHORT).show();
    }
    }

    public class registDB extends AsyncTask<Void, Integer, Void> {

    @Override
    protected Void doInBackground(Void... unused) {

    /* 인풋 파라메터값 생성 */
    String param = "u_id=" + sId + "u_pw=" + sPw + "";
    try {
    /* 서버연결 */
    URL url = new URL(
    "http://piu0625.cafe24.com/Signup/snclib_join.php";);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded";);
    conn.setRequestMethod("POST";);
    conn.setDoInput(true);
    conn.connect();

    /* 안드로이드 -> 서버 파라메터값 전달 */
    OutputStream outs = conn.getOutputStream();
    outs.write(param.getBytes("UTF-8";));
    outs.flush();
    outs.close();

    /* 서버 -> 안드로이드 파라메터값 전달 */
    InputStream is = null;
    BufferedReader in = null;
    String data = "";

    is = conn.getInputStream();
    in = new BufferedReader(new InputStreamReader(is), 8 * 1024);
    String line = null;
    StringBuffer buff = new StringBuffer();
    while ( ( line = in.readLine() ) != null )
    {
    buff.append(line + "\n";);
    }
    data = buff.toString().trim();
    Log.e("RECV DATA",data);

    } catch (MalformedURLException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }

    return null;
    }

    }


    }
    제가 똑같이 했는데...registDB 클래스가 활성이 안되서 안드로이드 앱을 실행 했을때 비밀번호 확인은 되는데..
    데이터베이스에 저장이 안됩니다...registDB클래스가 회색으로 되있으면 활성이 안되는게 맞지않나요?ㅜㅜ
    제가 혼자 공부를 해서 물어볼곳이 많이 없어서요ㅜㅜ시간 나실때 답변 쫌 주세요ㅠㅠ

    • 지나가다봅니다
      2017.08.25 11:14

      public void bt_Join(View view)
      {
      /* 버튼을 눌렀을 때 동작하는 소스 */
      sId = et_id.getText().toString();
      sPw = et_pw.getText().toString();
      sPw_chk = et_pw_chk.getText().toString();

      if(sPw.equals(sPw_chk))
      {
      /* 패스워드 확인이 정상적으로 됨 */
      registDB rdb = new registDB();
      rdb.execute();
      }
      else
      {
      /* 패스워드 확인이 불일치 함 */

      }
      }

      이부분을 사용안하신거같은데... class를 사용한곳이 없으니까 활성화가 되지 않습니다..
      확인해보세요

  • 쿼드
    2017.09.02 23:20

    좋은 강좌 감사드립니다.
    하지만 앱을 실행한뒤, 아이디, 비밀번호 다 입력하고, JOIN버튼을 누르면
    로그가 뜨는데, 그 로그의 내용이 그냥 snclib_join.php의 내용입니다.
    어떻게 된 오류인지 궁금합니다.

    • 2017.09.03 16:34 신고

      해당오류는 다음 포스팅 처음에서 다루었습니다 ^^

    • 감사요
      2019.08.30 23:37

      다음포스팅이 어떤 포스팅인가요?? [2] 말씀하시는건가요 저도 같은 오류인데 해결이안되고있어서 ..

    • 2019.09.03 08:07 신고

      다음 포스팅에 결과값 출력을 넣으시면 해결되실꺼에요~

  • 퍼미션
    2017.10.08 01:51

    안녕하세요. 좋은 글 잘 봤습니다.
    제가 겪은 시행착오에 대해 여러 사람에게 알려드리려고 합니다.

    분명히 똑같이 따라 했는데도 불구하고 DB에 등록이 안되서
    이래저래 검색하고 알아 본 결과 인터넷 사용관련 퍼미션이 필요하다는 것을 알았습니다.

    메니페스트 파일에 <uses-permission android:name="android.permission.INTERNET" /> 넣어주니 잘 되네요

    잘 안되는 다른 분들께 도움이 됬으면 좋겠네요 ^^

    • 2017.10.08 13:33 신고

      감사합니다 ^^

    • 의지의한국인
      2017.11.07 17:14

      와.. 한방에 해결;;

      정말 감사드립니다(=_=)(_ _)

    • 초보
      2017.12.19 21:28

      퍼미션님 댓글 아니었으면 진짜 하루종일
      헤맬뻔 했네요... 얼마나 먼 길을 돌아갔을지ㅠㅠ 정말 감사합니다 ㅠㅠㅠ 복받으실거에요 천사에요 사랑해요

  • 하하하
    2017.11.01 18:07

    많은 도움이 되었습니다. 감사합니다! 혹시 이 소스 파일로 받아볼 수 있나요??

  • 오와아앙
    2018.03.12 00:39

    헐 대박 완전 감사합니다 ㅠㅠ 이것보고 많이 따라했어요...!! 정보가 별로 없었는데 ㅠㅠ 감사합니다!! 그런데 저는 이름이랑 이메일, 비밀번호 세개까지 입력받아서 저장하려고 하는데 저장이 안되네요... 혹시 여기에 코드 올리면 한 번 봐주실 수 있으실까요..? 감사합니다 ㅜㅜ

  • dfd
    2018.05.16 19:56

    join.php
    <?
    header('content-type: text/html; charset=utf-8');
    // 데이터베이스 접속 문자열. (db위치, 유저 이름, 비밀번호)
    $connect=mysql_connect( "localhost","sunny4299","zoqtmxhs15.";) or
    die( "SQL server에 연결할 수 없습니다.";);

    mysql_query("SET NAMES UTF8";);
    // 데이터베이스 선택
    mysql_select_db("USER",$connect);

    // 세션 시작
    session_start();

    $id = $_POST[userId];
    $pw = $_POST[userPassword];

    $sql = "INSERT INTO USERS(userId, userPassword) VALUES('$userId', '$userPassword')";

    $result = mysql_query($sql);

    if(!$result)
    die("mysql query error";);
    else
    echo "insert success"

    ?>
    ----------------------------------------------------------------------------------------------
    //RegistActivity
    import android.content.Intent;
    import android.graphics.Color;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.text.Editable;
    import android.text.TextWatcher;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;

    /**
    * Created by USER on 2018-02-01.
    */

    public class RegistActivity extends AppCompatActivity {
    private EditText etEmail;
    private EditText etPassword;
    private EditText etPasswordConfirm;
    private Button btnDone;
    private Button btnCancel;
    String password;
    String confirm,id;

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

    etEmail = (EditText) findViewById(R.id.etEmail);
    etPassword = (EditText) findViewById(R.id.etPassword);
    etPasswordConfirm = (EditText) findViewById(R.id.etPasswordConfirm);
    btnDone = (Button) findViewById(R.id.btnDone);
    btnCancel = (Button) findViewById(R.id.btnCancel);

    // 비밀번호 일치 검사
    etPasswordConfirm.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    password = etPassword.getText().toString();
    confirm = etPasswordConfirm.getText().toString();

    if (password.equals(confirm)) {
    Toast.makeText(RegistActivity.this, "\n" +
    "비밀번호가 일치합니다 ", Toast.LENGTH_SHORT).show();
    /* 패스워드 확인이 정상적으로 됨 */


    } else {
    Toast.makeText(RegistActivity.this, "\n" +
    "비밀번호가 불 일치합니다 ", Toast.LENGTH_SHORT).show();
    }
    }


    @Override
    public void afterTextChanged(Editable s) {

    }
    });
    }
    public void btnDone(View view) {
    /* 버튼을 눌렀을 때 동작하는 소스 */
    id = etEmail.getText().toString();
    password = etPassword.getText().toString();
    confirm = etPasswordConfirm.getText().toString();

    if (password.equals(confirm)) {

    Toast.makeText(RegistActivity.this, "\n" +
    "비밀번호가 일치합니다 ", Toast.LENGTH_SHORT).show();

    /* 패스워드 확인이 정상적으로 됨 */
    registDB rdb = new registDB();
    rdb.execute();

    }
    else
    {
    Toast.makeText(RegistActivity.this, "\n" +
    "비밀번호가 불 일치합니다 ", Toast.LENGTH_SHORT).show();
    }
    }



    public class registDB extends AsyncTask<Void, Integer, Void> {

    @Override
    protected Void doInBackground(Void... unused) {

    /* 인풋 파라메터값 생성 */

    String param = "userId=" + password + "userPassword=" + confirm + "";

    try {
    /* 서버연결 */
    URL url = new URL(
    "http://uws64-100.cafe24.com/WebMysql/join.php";);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded";);
    conn.setRequestMethod("POST";);
    conn.setDoInput(true);
    conn.connect();

    /* 안드로이드 -> 서버 파라메터값 전달 */
    OutputStream outs = conn.getOutputStream();
    outs.write(param.getBytes("UTF-8";));
    outs.flush();
    outs.close();

    /* 서버 -> 안드로이드 파라메터값 전달 */
    InputStream is = null;
    BufferedReader in = null;
    String data = "";

    is = conn.getInputStream();
    in = new BufferedReader(new InputStreamReader(is), 8 * 1024);
    String line = null;
    StringBuffer buff = new StringBuffer();
    while ((line = in.readLine()) != null) {
    buff.append(line + "\n";);
    }
    data = buff.toString().trim();
    Log.e("RECV DATA", data);

    } catch (MalformedURLException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }

    return null;
    }

    }
    }
    아무리해도 저장이 안되네요ㅠㅠㅠ
    혹시 어디부분이 잘 못 됐는지 알려주실 수 있을까요??ㅠㅠ

    • 2018.05.17 08:51 신고

      안녕하세요~ 일단 어느부분에서 안되는지를 파악해야되는데 PHP에서 쿼리에 UserID, PW를 임의로 넣고 실행해보세요. DB에 들어가면 일단 php->db는 문제없습니다. 그다음엔 php에서 echo로 넘어온 id와 pw를 찍어보시고, 그다음엔 안드로이드에서 php로 보내기전에 데이터를 찍어보세요. 하나씩 찍어보시다 보면 안되는 부분을 찾을 수 있을꺼에요~

  • 간절함
    2018.11.16 18:54

    package com.example.user.login;

    import android.os.AsyncTask;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;

    public class MainActivity extends AppCompatActivity {

    EditText et_id, et_pw, et_pw_chk;
    String sId, sPw, sPw_chk;


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

    et_id = (EditText) findViewById(R.id.et_Id);
    et_pw = (EditText) findViewById(R.id.et_Password);
    et_pw_chk = (EditText) findViewById(R.id.et_Password_chk);

    Button button = (Button)findViewById(R.id.bt_Join);

    button.setOnClickListener(new Button.OnClickListener() {
    @Override
    public void onClick(View v) {
    sId = et_id.getText().toString();
    sPw = et_pw.getText().toString();
    sPw_chk = et_pw_chk.getText().toString();

    if (sPw.equals(sPw_chk)) {
    Toast.makeText(getApplicationContext(), "일치합니다", Toast.LENGTH_SHORT).show();
    registerDB rdb = new registerDB();
    rdb.execute();
    } else {
    Toast.makeText(getApplicationContext(), "불일치합니다", Toast.LENGTH_SHORT).show();
    }
    }
    });
    }

    public class registerDB extends AsyncTask<Void, Integer, Void> {
    protected Void doInBackground(Void... unused) {


    /* 인풋 파라메터값 생성 */
    String param = "u_id=" + sId + "&u_pw=" + sPw + "";
    try {
    /* 서버연결 */
    URL url = new URL(
    "http://127.0.0.1/snclib_join.php";);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded";);
    conn.setRequestMethod("POST";);
    conn.setDoInput(true);
    conn.connect();

    /* 안드로이드 -> 서버 파라메터값 전달 */
    OutputStream outs = conn.getOutputStream();
    outs.write(param.getBytes("UTF-8";));
    outs.flush();
    outs.close();

    /* 서버 -> 안드로이드 파라메터값 전달 */
    InputStream is = null;
    BufferedReader in = null;
    String data = "";

    is = conn.getInputStream();
    in = new BufferedReader(new InputStreamReader(is), 8 * 1024);
    String line = null;
    StringBuffer buff = new StringBuffer();
    while ((line = in.readLine()) != null) {
    buff.append(line + "\n";);
    }
    data = buff.toString().trim();
    Log.e("RECV DATA", data);

    } catch (MalformedURLException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }

    return null;
    }

    }
    }
    일치합니다 까지는 뜨는데 왜 디비로 안넘어가느지 잘모르겠어요..ㅠ

  • 어렵당어
    2019.09.19 16:03

    질문있어서 남겨요ㅜㅜ connection refused는 왜 뜨는걸까요??? 서버에 문제가 있나 싶어서 확인해봤는데 접속도 잘되고 보안그룹 설정도 모드 접근가능하게 설정되어있습니다.

    • 2019.09.19 16:06 신고

      안드로이드 에러창에서 거절되나요~? 인터넷 퍼미션 확인해보시고 혹시 에뮬레이터로 하시는거면 기기로도 해보세요~

Designed by JB FACTORY