** 해야 할 일

1. select from DB => show Android ()

2. input Android => insert data to DB

 


** use DataBase : MySQL

** Setting ("xampp\htdocts" 에서 php 파일 보관)

use DataBase(DBMS) MySQL(PHPMyAdmin) Environment Windows10
web Server Apatch(localhost, 개이IP) etc 통합 환경 XAMPP 사용

 

여러번 삽질을 해본 결과... 사실 연동이라 함은 깔끔하게 데이터만 뽑아서 가져올법 하지만, 그건 모두 개발자의 몫이다.. 따라서 원하는 데이터가 있다면 먼저 DB에서 php 화면에 데이터를 불러와서 띄운다음에, 그 띄운 글자를 안드로이드에 배열 형태로 가져온다. 그리고 배열에서 '[' 같은 문자를 파싱하고 출력하면 내가 처음에 원하는 것이 나온다...

주로 이런 값 전달은 phpecho "전달할값"$변수명 으로 통한다. 안드로이드에서 쓴 글씨를 DB에 넣지 않고 php 상에서 본다는건... 사실상 좀 까다로운 일 같다.., 될 수 있는지도 모르겠다..

"안드로이드에서 받은 값을 DB에서 넣지 않고 php 상에 띄운다""안드로이드에서 입력한 값을 php로 보내서 echo로 출력하면 그 출력 데이터가 다시 돌아와 안드로이드에서 출력된다" 와 같은 의미였다... 하긴, 동적인 값을 어떻게 php에서 받아서 바로바로 출력해줄 수 있겠어...

 

** 1. select from DB => show Android

1) Select from DB - PHP

안드로이드에서 DB의 값을 출력하고싶다면, 먼저 DB에서 값을 가져와 PHP에 출력하는 작업이 필요하다. 사실상 출력이라기보다는 값전달에 가깝다. PHP 화면상에 DB의 값이 출력되는건 echo 함수로 값을 전달 할 수 밖에 없기 때문에 보여질 수 밖에 없는 것이다..

다음은 DB에서 값을 읽어와 php에 출력하는 코드.

- insertData.php

<?php
    // DB 연동을 시작합니다.
    $con=mysqli_connect("호스트명", "DB ID", "DB PW", "DB 이름");

    // mysqli_connect()에 대한 마지막 호출에 대한 오류 코드 값을 반환한다.
    // echo mysqli_connect() 에서 0은 오류가 발생하지 않았음을 의미한다
    if (mysqli_connect_errno($con)) {
        echo "Failed to connect to MySQL: " . mysqli_connect_error();
    }


    /* select data */
    // 1. 실행할 쿼리문을 작성합니다.
    $selectSQL = "select * from ttest";
    $result = mysqli_query($con, $selectSQL);

    // 출력할 데이터를 저장할 배열변수 선언
    // 데이터는 json-array 형식으로 출력할 것임 (일반적으로 이렇게 함)
    $data = array();
    
    if ($result) {
        while ($row=mysqli_fetch_array($result)) {
            array_push($data,array('컬럼명'=>$row[0],'컬럼명'=>$row[1]));
        }
        header('Content-Type: application/json; charset=utf8');
        $json = json_encode(array("테이블이름"=>$data), JSON_PRETTY_PRINT+JSON_UNESCAPED_UNICODE);

		echo $json; // => 출력되는 값이 이 코드로 하여금 android로 전송된다..

	} else {
        echo "SQL문 처리중 에러 발생 : ";
        echo mysqli_error($con);
    }

    // DB 연동을 종료 합니다
    mysqli_close($con);
?>

여기서, if 문을 살펴보자

array_push($data,array('컬럼명'=>$row[0],'컬럼명'=>$row[1]));

배열로 선언한 data 변수에 첫번째 컬럼명(row[0]), 두번째 컬럼명(row[1]) 을 연관배열의 형태로 저장한다. 이 부분은 필요하다면 for을 사용해서 더 깔끔하게 코딩할 수 있다.. 나는 그냥 필요한 만큼만 했다.. 여기서 '컬럼명'은 연관배열로 지정해줄 이름일뿐, 굳이 컬럼명을 적지 않아도 된다!!! 대신 컬럼명이 아닌데 컬럼 값을 가지고 있으면, 다른 사람이 볼 때 어떤 값인지.. 잘 알아볼 수 있을까..ㅎ

$json = json_encode(array("테이블이름"=>$data), JSON_PRETTY_PRINT+JSON_UNESCAPED_UNICODE); 

json이라는 변수를 선언하고 아까 data 배열 변수를 json 코드로 인코딩해서 저장했다. 뒤에 있는건 추가적으로 json 배열이 더 예쁘게 내보이고 싶다면 사용하는 옵션이다. 더 필요한 옵션이 있다면 구글링을 하시도록!

 

2) Show Android - Android Programming

- activity_main.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"
    android:orientation="vertical"
    android:layout_margin="40dp"
    android:gravity="center"
    tools:context=".MainActivity">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <EditText
            android:id="@+id/edtText1"
            android:hint="ID"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <EditText
            android:id="@+id/edtText2"
            android:hint="PW"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <LinearLayout
            android:gravity="center"
            android:layout_marginTop="20dp"
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <Button
                android:id="@+id/insertBtn"
                android:text="insert"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </LinearLayout>
    <LinearLayout
        android:orientation="vertical"
        android:layout_marginTop="80dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/txtView"
            android:text="test txt"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</LinearLayout>

 

- MainActivity.java

public class MainActivity extends AppCompatActivity {

    private TextView txtView;
    private EditText editText1, editText2;
    Button insertBtn;

    private static String IP = ""; //서버 없이 사용하는 IP가 있다면 저장해서 사용하면 된다.

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

		// 사용할 액티비티 선언
        editText1 = findViewById(R.id.edtText1);
        editText2 = findViewById(R.id.edtText2);
        insertBtn = findViewById(R.id.insertBtn);

		// String url = "http://" + IP + "/php파일명.php";
        String url = "http://" + IP + "/InsertData.php";
        selectDatabase selectDatabase = new selectDatabase(url, null);
        selectDatabase.execute(); // AsyncTask는 .excute()로 실행된다.

    }


    class selectDatabase extends AsyncTask<Void, Void, String> {

        private String url1;
        private ContentValues values1;
        String result1; // 요청 결과를 저장할 변수.

        public selectDatabase(String url, ContentValues contentValues) {
            this.url1 = url;
            this.values1 = contentValues;
        }
        
        @Override
        protected String doInBackground(Void... params) {
            RequestHttpURLConnection requestHttpURLConnection = new RequestHttpURLConnection();
            result1 = requestHttpURLConnection.request(url1, values1); // 해당 URL로 부터 결과물을 얻어온다.
            return result1; // 여기서 당장 실행 X, onPostExcute에서 실행
        }
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            //txtView.setText(s); // 파서 없이 전체 출력
            doJSONParser(s); // 파서로 전체 출력
        }
    }

	// 받아온 json 데이터를 파싱합니다..
    public void doJSONParser(String string) {
        try {
            String result = "";
            JSONObject jsonObject = new JSONObject(string);
            JSONArray jsonArray = jsonObject.getJSONArray("ttest");

            for (int i=0; i < jsonArray.length(); i++) {
                JSONObject output = jsonArray.getJSONObject(i);
                result += output.getString("ed1txt")
                        + " / "
                        + output.getString("ed2txt")
                        + "\n";
            }

            txtView = findViewById(R.id.txtView);
            txtView.setText(result);

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

}

 

- RequestHttpURLConnection.java

public class RequestHttpURLConnection {

        public String request(String _url, ContentValues _params){

            // HttpURLConnection 참조 변수.
            HttpURLConnection urlConn = null;
            // URL 뒤에 붙여서 보낼 파라미터.
            StringBuffer sbParams = new StringBuffer();

            /**
             * 1. StringBuffer에 파라미터 연결
             * */
            // 보낼 데이터가 없으면 파라미터를 비운다.
            if (_params == null)
                sbParams.append("");
                // 보낼 데이터가 있으면 파라미터를 채운다.
            else {
                // 파라미터가 2개 이상이면 파라미터 연결에 &가 필요하므로 스위칭할 변수 생성.
                boolean isAnd = false;
                // 파라미터 키와 값.
                String key;
                String value;

                for(Map.Entry<String, Object> parameter : _params.valueSet()){
                    key = parameter.getKey();
                    value = parameter.getValue().toString();

                    // 파라미터가 두개 이상일때, 파라미터 사이에 &를 붙인다.
                    if (isAnd)
                        sbParams.append("&");

                    sbParams.append(key).append("=").append(value);

                    // 파라미터가 2개 이상이면 isAnd를 true로 바꾸고 다음 루프부터 &를 붙인다.
                    if (!isAnd)
                        if (_params.size() >= 2)
                            isAnd = true;
                }
            }

            /**
             * 2. HttpURLConnection을 통해 web의 데이터를 가져온다.
             * */
            try{
                URL url = new URL(_url);
                urlConn = (HttpURLConnection) url.openConnection();

                // [2-1]. urlConn 설정.
                urlConn.setRequestMethod("POST"); // URL 요청에 대한 메소드 설정 : POST.
                urlConn.setRequestProperty("Accept-Charset", "UTF-8"); // Accept-Charset 설정.
                urlConn.setRequestProperty("Context_Type", "application/x-www-form-urlencoded;cahrset=UTF-8");

                // [2-2]. parameter 전달 및 데이터 읽어오기.
                String strParams = sbParams.toString(); //sbParams에 정리한 파라미터들을 스트링으로 저장. 예)id=id1&pw=123;
                OutputStream os = urlConn.getOutputStream();
                os.write(strParams.getBytes("UTF-8")); // 출력 스트림에 출력.
                os.flush(); // 출력 스트림을 플러시(비운다)하고 버퍼링 된 모든 출력 바이트를 강제 실행.
                os.close(); // 출력 스트림을 닫고 모든 시스템 자원을 해제.

                // [2-3]. 연결 요청 확인.
                // 실패 시 null을 리턴하고 메서드를 종료.
                if (urlConn.getResponseCode() != HttpURLConnection.HTTP_OK)
                    return null;

                // [2-4]. 읽어온 결과물 리턴.
                // 요청한 URL의 출력물을 BufferedReader로 받는다.
                BufferedReader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream(), "UTF-8"));

                // 출력물의 라인과 그 합에 대한 변수.
                String line;
                String page = "";

                // 라인을 받아와 합친다.
                while ((line = reader.readLine()) != null){
                    page += line;
                }

                return page;

            } catch (MalformedURLException e) { // for URL.
                e.printStackTrace();
            } catch (IOException e) { // for openConnection().
                e.printStackTrace();
            } finally {
                if (urlConn != null)
                    urlConn.disconnect();
            }

            return null;
        }
}

 

- NetworkTask.java

public class NetworkTask extends AsyncTask<Void, Void, String> {

        private String url;
        private ContentValues values;

        public NetworkTask(String url, ContentValues values) {

            this.url = url;
            this.values = values;
        }

        @Override
        protected String doInBackground(Void... params) {

            String result; // 요청 결과를 저장할 변수.
            RequestHttpURLConnection requestHttpURLConnection = new RequestHttpURLConnection();
            result = requestHttpURLConnection.request(url, values); // 해당 URL로 부터 결과물을 얻어온다.

            return result;
        }

}

insert도 비슷하니까 설명 생략하고 그냥 코드 복붙..

 

** 2. input Android => insert data to DB

1) Type input data - Android

- insertData.php (코드 추가함)

<?php

/* insert data */
    // 1. 안드로이드에서 post로 날린 값을 받아 변수에 저장합니다
    $ed1txt = $_POST['ed1txt'];
    $ed2txt = $_POST['ed2txt'];

    // 2. 실행할 쿼리문을 작성합니다. => mysqli_query(실행할 Db, 실행할 query)
    $insertSQL = "insert into ttest (ed1txt,ed2txt) values ('$ed1txt','$ed2txt')";
    $result1 = mysqli_query($con, $insertSQL);

    if ($result1) {
        echo "Success!!";
    } else {
        echo "Fail insert data to Database...";
    }
    
    ?>

 

2) Insert data to DB - PHP

- MainActivity.java (코드 추가함)

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

        insertBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                insertoToDatabase(editText1.getText().toString(),editText2.getText().toString());
            }
        });

    }

    private void insertoToDatabase(final String ed1, String ed2) {
        class InsertData extends AsyncTask<String, Void, String> {
            ProgressDialog loading;

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                loading = ProgressDialog.show(MainActivity.this, "Please Wait", null, true, true);
            }
            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                loading.dismiss();
                //Log.d("Tag : ", s); // php에서 가져온 값을 최종 출력함
                Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();
            }
            @Override
            protected String doInBackground(String... params) {

                try {
                    String edt1Text = (String) params[0];
                    String edt2Text = (String) params[1];

                    String link = "http://"+cafeIP+"/InsertData.php";
                    String data = URLEncoder.encode("ed1txt", "UTF-8") + "=" + URLEncoder.encode(edt1Text, "UTF-8");
                    data += "&" + URLEncoder.encode("ed2txt", "UTF-8") + "=" + URLEncoder.encode(edt2Text, "UTF-8");

                    URL url = new URL(link);
                    URLConnection conn = url.openConnection();

                    conn.setDoOutput(true);
                    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(conn.getOutputStream());
                    outputStreamWriter.write(data);
                    outputStreamWriter.flush();

                    BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));

                    StringBuilder sb = new StringBuilder();
                    String line = null;

                    // Read Server Response
                    while ((line = reader.readLine()) != null) {
                        sb.append(line);
                        break;
                    }
                    Log.d("tag : ", sb.toString()); // php에서 결과값을 리턴
                    return sb.toString();

                } catch (Exception e) {
                    return new String("Exception: " + e.getMessage());
                }
            }
        }
        InsertData task = new InsertData();
        task.execute(ed1,ed2);
    }

 

 


** 헉 대박 이거 잊으면 안됨 꼭 해야함

** manifest 셋팅

- AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:usesCleartextTraffic="true">
    </application>

</manifest>

 

1. 인터넷 퍼미션

2. thread 오류가 나도 계속 진행하게함.

 


 

 

+ Recent posts