본문 바로가기
안드로이드 웹앱 콘테츠 개발자 양성(국비지원)/HTML 도메인

HTTP 서버와 DB 앱 연동 (텍스트,이미지를 GET,POST로 DB까지) 1-2

by 차누감 2019. 10. 22.

앱에서 기재한 텍스트와 휴대폰에 있는 이미지를 웹서버에 올리고

그 해당 값을 DB에 저장하는 예제이다.

HTTP 서버와 DB 앱 연동 (텍스트,이미지를 GET,POST로 DB까지) 1-1에서 이미지 업로드 버튼 기능까지 했다.

이제 남은 Load data 버튼 기능을 하겠다. (DB에 저장된 데이터 가져오기.)

 

새로운 액티비티(TalkActivity)를 만들어서 가져오는데, loadDB.php도 만들 것이다.

 

액티비티를 만들자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    tools:context=".TalkActivity">
 
    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
 
</RelativeLayout>
 
 

TalkActivity.java 내용은 나중에 코드 작성할거임

이제 대량의 데이터를 만들자.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
 
public class TalkItem {
    int no;
    String name;
    String msg;
    String imgPath;
    String date;
 
    public TalkItem(int no, String name, String msg, String imgPath, String date) {
        this.no = no;
        this.name = name;
        this.msg = msg;
        this.imgPath = imgPath;
        this.date = date;
    }
 
    public int getNo() {
        return no;
    }
 
    public void setNo(int no) {
        this.no = no;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getMsg() {
        return msg;
    }
 
    public void setMsg(String msg) {
        this.msg = msg;
    }
 
    public String getImgPath() {
        return imgPath;
    }
 
    public void setImgPath(String imgPath) {
        this.imgPath = imgPath;
    }
 
    public String getDate() {
        return date;
    }
 
    public void setDate(String date) {
        this.date = date;
    }
}
 
 
 

대량의 데이터들 화면 구성 / Linear로 만들었지만 CardView를 쓸것임 (라이브러리 추가 밑에 나옴)
Cardview를 쓰기 위해 라이브러리 추가

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?xml version="1.0" encoding="utf-8"?>
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="400dp"
    app:cardBackgroundColor="#dd8800"
    app:cardElevation="4dp"
    app:contentPadding="4dp">
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
 
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
 
            <TextView
                android:id="@+id/tv_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="name"
                android:textColor="#006600"
                android:textStyle="bold"
                android:textSize="14sp"
                android:padding="4dp"/>
 
            <TextView
                android:id="@+id/tv_date"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="2019-10-22 09:26:30"
                android:textColor="#ffffff"
                android:textSize="8sp"
                android:padding="4dp"
                android:layout_alignParentRight="true"/>
 
        </RelativeLayout>
        <TextView
            android:id="@+id/tv_msg"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="message region"
            android:textColor="#ffffff"
            android:textStyle="bold"
            android:padding="4dp"/>
 
        <ImageView
            android:id="@+id/iv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"/>
    </LinearLayout>
 
 
 

이제 대량의 데이터를 연결해줄 Adapter를 만들자.

TalkAdapter에서 이미지를 ImageView에 띄우려고, glide라이브러리 추가하자.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 
 
 
 
public class TalkAdapter extends BaseAdapter {
 
    LayoutInflater inflater;
    ArrayList<TalkItem> talkItems;
 
    public TalkAdapter(LayoutInflater inflater, ArrayList<TalkItem> talkItems) {
        this.inflater = inflater;
        this.talkItems = talkItems;
    }
 
    @Override
    public int getCount() {
        return talkItems.size();
    }
 
    @Override
    public Object getItem(int position) {
        return talkItems.get(position);
    }
 
    @Override
    public long getItemId(int position) {
        return position;
    }
 
    @Override
    public View getView(int position, View view, ViewGroup viewGroup) {
 
        if(view==null){
            view= inflater.inflate(R.layout.list_item, viewGroup, false);
        }
 
        TextView tvName= view.findViewById(R.id.tv_name);
        TextView tvDate= view.findViewById(R.id.tv_date);
        TextView tvMsg= view.findViewById(R.id.tv_msg);
        ImageView iv= view.findViewById(R.id.iv);
 
        TalkItem talkItem= talkItems.get(position);
        tvName.setText(talkItem.getName());
        tvName.setText(talkItem.getDate());
        tvName.setText(talkItem.getMsg());
 
        //네트워크에 있는 이미지 읽어오기.
 
        return view;
    }
}
 
 
 

이제 TalkActivity 코드를 작성하자.

TalkActivity.java 코드

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
 
 
 
 
public class TalkActivity extends AppCompatActivity {
 
    ListView listView;
    TalkAdapter talkAdapter;
 
    ArrayList<TalkItem> talkItems= new ArrayList<>();
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_talk);
 
        //데이터를 서버에서 읽어오기
        loadDB();
 
        listView= findViewById(R.id.listView);
        talkAdapter= new TalkAdapter(getLayoutInflater(),talkItems);
        listView.setAdapter(talkAdapter);
 
    }
 
    void loadDB(){
        //volley library로 사용 가능
        //이 예제에서는 전통적 기법으로 함.
        new Thread(){
            @Override
            public void run() {
 
                String serverUri="http://umul.dothome.co.kr/Android/loadDB.php";
 
                try {
                    URL url= new URL(serverUri);
 
                    HttpURLConnection connection= (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setDoInput(true);
                    //connection.setDoOutput(true);// 이 예제는 필요 없다.
                    connection.setUseCaches(false);
 
                    InputStream is=connection.getInputStream();
                    InputStreamReader isr= new InputStreamReader(is);
                    BufferedReader reader= new BufferedReader(isr);
 
                    final StringBuffer buffer= new StringBuffer();
                    String line= reader.readLine();
                    while (line!=null){
                        buffer.append(line+"\n");
                        line= reader.readLine();
                    }
 
                    //읽어오는 작업이 성공 했는지 확인
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            new AlertDialog.Builder(TalkActivity.this).setMessage(buffer.toString()).create().show();
                        }
                    });
 
                } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) {e.printStackTrace();}
            }
        }.start();
    }//loadDB() ..
}
 
 
 

이제 loadDB.php를 만들자.

 

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
<?php
 
    header('Content-Type:text/html; charset=utf-8');
 
    $conn= mysqli_connect("localhost","umul","aa142536!","umul");
    //$conn= mysqli_connect("localhost","umul","aa142536!","umul");
 
    mysqli_query($conn"set names utf8");    //한글 깨짐 방지
 
    //쿼리문 작성
    $sql="select * from talk";
    $result=mysqli_query($conn$sql);
 
    //$result : 결과 표
 
    //결과의 총 레코드 수(줄 수, 행의 개수)
    $rowCnt= mysqli_num_rows($result);
 
    //레코드 수 만큼 반복하여 한줄씩 데이터 읽어오기
    for($i=0$i<$rowCnt$i++){
        //데이터 한줄을 연관배열(키값으로 구분)로 받아오기
        $row= mysqli_fetch_array($result, MYSQLI_ASSOC);
        echo "$row[no]&$row[name]&$row[message]&$row[imgPath]&$row[date];";
    }
 
    mysqli_close($conn);
 
?>
 
 

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
 
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
 
import android.Manifest;
import android.provider.MediaStore;
 
 
public class MainActivity extends AppCompatActivity {
 
    EditText etName,etMsg;
    ImageView iv;
 
    //업로드할 이미지의 절대경로(실제 경로)
    String imgPath;
 
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        etName=findViewById(R.id.et_name);
        etMsg=findViewById(R.id.et_msg);
        iv=findViewById(R.id.iv);
 
        //업로드 하려면 외부저장소 권한 필요
        //동적 퍼미션 코드 필요..
 
 
        //동적퍼미션 작업
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
            int permissionResult= checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
            if(permissionResult== PackageManager.PERMISSION_DENIED){
                String[] permissions= new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE};
                requestPermissions(permissions,10);
            }
        }else{
            //cv.setVisibility(View.VISIBLE);
        }
 
 
    }//onCreate() ..
 
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode){
            case 10 :
                if(grantResults[0]==PackageManager.PERMISSION_GRANTED) //사용자가 허가 했다면
                {
                    Toast.makeText(this"외부 메모리 읽기/쓰기 사용 가능", Toast.LENGTH_SHORT).show();
 
                }else{//거부했다면
                    Toast.makeText(this"외부 메모리 읽기/쓰기 제한", Toast.LENGTH_SHORT).show();
 
                }
                break;
        }
    }
 
    public void clickBtn(View view) {
 
        //갤러리 or 사진 앱 실행하여 사진을 선택하도록..
        Intent intent= new Intent(Intent.ACTION_PICK);
       intent.setType("image/*");
       startActivityForResult(intent,10);
    }
 
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
 
        switch (requestCode){
            case 10:
                if(resultCode==RESULT_OK){
                    //선택한 사진의 경로(Uri)객체 얻어오기
                    Uri uri= data.getData();
                    if(uri!=null){
                        iv.setImageURI(uri);
 
                        //갤러리앱에서 관리하는 DB정보가 있는데, 그것이 나온다 [실제 파일 경로가 아님!!]
                        //얻어온 Uri는 Gallery앱의 DB번호임. (content://-----/2854)
                        //업로드를 하려면 이미지의 절대경로(실제 경로: file:// -------/aaa.png 이런식)가 필요함
                        //Uri -->절대경로(String)로 변환
                        imgPath= getRealPathFromUri(uri);   //임의로 만든 메소드 (절대경로를 가져오는 메소드)
 
                        //이미지 경로 uri 확인해보기
                        new AlertDialog.Builder(this).setMessage(uri.toString()+"\n"+imgPath).create().show();
                    }
 
                }else
                {
                    Toast.makeText(this"이미지 선택을 하지 않았습니다.", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }//onActivityResult() ..
 
        //Uri -- > 절대경로로 바꿔서 리턴시켜주는 메소드
        String getRealPathFromUri(Uri uri){
            String[] proj= {MediaStore.Images.Media.DATA};
            CursorLoader loader= new CursorLoader(this, uri, proj, nullnullnull);
            Cursor cursor= loader.loadInBackground();
            int column_index= cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            String result= cursor.getString(column_index);
            cursor.close();
            return  result;
        }
 
    public void clickUpload(View view) {
 
        //서버로 보낼 데이터
        String name= etName.getText().toString();
        String msg= etMsg.getText().toString();
 
        //안드로이드에서 보낼 데이터를 받을 php 서버 주소
        String serverUrl="http://umul.dothome.co.kr/Android/insertDB.php";
 
        //Volley plus Library를 이용해서
        //파일 전송하도록..
        //Volley+는 AndroidStudio에서 검색이 안됨 [google 검색 이용]
 
        //파일 전송 요청 객체 생성[결과를 String으로 받음]
        SimpleMultiPartRequest smpr= new SimpleMultiPartRequest(Request.Method.POST, serverUrl, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                new AlertDialog.Builder(MainActivity.this).setMessage("응답:"+response).create().show();
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Toast.makeText(MainActivity.this"ERROR", Toast.LENGTH_SHORT).show();
            }
        });
 
        //요청 객체에 보낼 데이터를 추가
        smpr.addStringParam("name", name);
        smpr.addStringParam("msg", msg);
        //이미지 파일 추가
        smpr.addFile("img", imgPath);
 
        //요청객체를 서버로 보낼 우체통 같은 객체 생성
        RequestQueue requestQueue= Volley.newRequestQueue(this);
        requestQueue.add(smpr);
 
    }
 
    public void clickLoad(View view) {
 
        Intent intent= new Intent(this, TalkActivity.class);
        startActivity(intent);
    }
}
 
 
 

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
 
 
 
 
public class TalkActivity extends AppCompatActivity {
 
    ListView listView;
    TalkAdapter talkAdapter;
 
    ArrayList<TalkItem> talkItems= new ArrayList<>();
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_talk);
 
        //데이터를 서버에서 읽어오기
        loadDB();
 
        listView= findViewById(R.id.listView);
        talkAdapter= new TalkAdapter(getLayoutInflater(),talkItems);
        listView.setAdapter(talkAdapter);
 
    }
 
    void loadDB(){
        //volley library로 사용 가능
        //이 예제에서는 전통적 기법으로 함.
        new Thread(){
            @Override
            public void run() {
 
                String serverUri="http://umul.dothome.co.kr/Android/loadDB.php";
 
                try {
                    URL url= new URL(serverUri);
 
                    HttpURLConnection connection= (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setDoInput(true);
                    //connection.setDoOutput(true);// 이 예제는 필요 없다.
                    connection.setUseCaches(false);
 
                    InputStream is=connection.getInputStream();
                    InputStreamReader isr= new InputStreamReader(is);
                    BufferedReader reader= new BufferedReader(isr);
 
                    final StringBuffer buffer= new StringBuffer();
                    String line= reader.readLine();
                    while (line!=null){
                        buffer.append(line+"\n");
                        line= reader.readLine();
                    }
 
                    //읽어온 문자열에서 row(레코드)별로 분리하여 배열로 리턴하기
                    String[] rows=buffer.toString().split(";");
 
                    //대량의 데이터 초기화
                    talkItems.clear();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            talkAdapter.notifyDataSetChanged();
                        }
                    });
 
                    for(String row : rows){
                        //한줄 데이터에서 한 칸씩 분리
                        String[] datas=row.split("&");
                        if(datas.length!=5continue;
 
                        int no= Integer.parseInt(datas[0]);
                        String name=datas[1];
                        String msg=datas[2];
                        String imgPath= "http://umul.dothome.co.kr/Android/"+datas[3];   //이미지는 상대경로라서 앞에 서버 주소를 써야한다.
                        String date=datas[4];
 
                        //대량의 데이터 ArrayList에 추가
                        talkItems.add(new TalkItem(no,name,msg,imgPath,date));
 
                        //리스트뷰 갱신
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                talkAdapter.notifyDataSetChanged();
                            }
                        });
                    }
//                    //읽어오는 작업이 성공 했는지 확인
//                    runOnUiThread(new Runnable() {
//                        @Override
//                        public void run() {
//                            new AlertDialog.Builder(TalkActivity.this).setMessage(buffer.toString()).create().show();
//
//
//                        }
//                    });
 
                } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) {e.printStackTrace();}
            }
        }.start();
    }//loadDB() ..
}
 
 
 

<LOAD DATA 버튼 실행 화면>

DB에 저장된 데이터를 가져와서 보여준다.

 

댓글