반응형

미니 플젝으로 평소에 만들어보고 싶었던 '부산 버스' 어플을 구현하였다.


API는 공공데이터 포털(data.go.kr)에서 받아왔으며 xml로 파싱하여 값을 받아왔다.


api 파싱과 값 뽑아오는 부분에서는 정말 맨땅에 헤딩이어서 이틀 밤샘 삽질하다가 겨우겨우 해결했다ㅠㅠ


http://movie13.tistory.com/1 << 여기 이 블로그에서 많은 도움을 받았다!!


위의 사이트에서 원하는 api를 검색 후 활용신청하고 end point 와 service key를 받아놓는다. 참고문서도 내려받아서 참고하면된다.


UI부분에 좀 더 투자를 하고 싶었지만 값을 받아내는데 급급해서 사진만 넣고 스크롤뷰에 textview만 넣었다..


<레이아웃>



버스번호와 정류장 번호를 입력하면 해당 정류장에 입력한 버스가 언제 도착하는지를 알려준다.



근데.. 제작 다하고 발표하는 날에 치명적인 오류가 발생하였다..



????? 현재시각 오전 11:13 인데 절대 버스가 없을리가 없는데 왜이렇지 하고 코드분석을 했는데...


알고보니


띠용 ...... 이럴수가....


이 상태가 된지 2주가 넘은거같은데 처리 부탁드립니다...(_ _)


아래는 안드로이드에서 작업한 xml과 java코드이다.



<activity_main.xml>

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
<?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:background="@drawable/road"
    android:orientation="vertical"
    android:weightSum="10"
    tools:context=".MainActivity">
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="vertical">
 
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="언제 도착하지?"
            android:textColor="#ffffffff"
            android:textSize="40dp" />
    </LinearLayout>
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="4"
        android:orientation="vertical"
        android:weightSum="5">
 
        <EditText
            android:id="@+id/busNum"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="2"
            android:background="@null"
            android:ems="10"
            android:hint="버스 번호를 입력해주세요."
            android:inputType="textPersonName"
            android:text=""
            android:textColor="#ffffffff"
            android:textColorHint="#D5D5D5" />
 
        <EditText
            android:id="@+id/stationArsno"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="2"
            android:background="@null"
            android:ems="10"
            android:hint="정류장 번호를 입력해주세요."
            android:inputType="textPersonName"
            android:text=""
            android:textColor="#ffffffff"
            android:textColorHint="#D5D5D5" />
 
 
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:onClick="search"
            android:text="검색하기" />
    </LinearLayout>
 
 
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="5"
        android:background="@color/colorBlack">
 
        <TextView
            android:id="@+id/showInfo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text=""
            android:textColor="#ffffffff"
            android:textSize="20dp" />
    </ScrollView>
 
</LinearLayout>
cs


<MainActivity.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
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
package com.example.sh.bus;
 
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
 
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
 
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class MainActivity extends AppCompatActivity {
 
    private final String TAG = "myTag";
    private final String key = "WyP9pjBjktC%2Bea2fFObCERMWEwTJGwwsRMr1YeyFGuqKZSnQwmKcnk1n3ZKf6L8UMGjCSZ4HZDCC%2BSQol89tjQ%3D%3D";
    private final String endPoint = "http://61.43.246.153/openapi-data/service/busanBIMS2";
 
    //xml 변수
    private EditText xmlBusNum;
    private EditText xmlStationArsno;
    private TextView xmlShowInfo;
 
    // 파싱을 위한 필드 선언
    private URL url;
    private InputStream is;
    private XmlPullParserFactory factory;
    private XmlPullParser xpp;
    private String tag;
    private int eventType;
 
    // xml의 값 입력 변수
    private String busNum; // 버스 번호
    private String stationArsno = ""//출발 정류장 arsNo
    private StringBuffer buffer;
    // 데이터 검색
    private String busNumId; // 버스 번호 Id
    private String stationId;// 출발 정류소명 Id
    private String sStationArriveTime; // 버스의 정류장 도착정보
 
    private String car1;
    private String min1;
    private String station1;
    private String car2;
    private String min2;
    private String station2;
 
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //상태바 없애기(FullScreen)
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_main);
 
        //xml 아이디 얻어오기
        getXmlId();
        buffer = new StringBuffer();
    }
    //검색하기 onclick버튼
    public void search(View view) {
        //사용자한테 출발정류장, 도착정류장 알아오기.
        busNum = xmlBusNum.getText().toString();
        stationArsno = xmlStationArsno.getText().toString();
        car1 = min1 = station1 = car2 = min2 = station2 = null;
        buffer = null;
        buffer = new StringBuffer();
        xmlShowInfo.setText("");
 
        //입력값 검사 함수
        if(exmineData()) {
            // 입력값 검사 함수에서 true를 return할 경우 값이 잘못된 것..
            // 종료..
            return;
        }
 
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 검색한 버스 id 얻기
                // 오퍼레이션 2
                getBusId(busNum);
 
                //검색한 정류장 얻기
                //오퍼레이션 1
                getStationId(stationArsno);
 
                //버스가 언제오는지 확인
                //오퍼레이션 5
                userWant(busNumId, stationId);
 
                // UI setText 하는 곳..
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Log.d(TAG, car1 + " " + min1 + " " + station1);
                        Log.d(TAG, car2 + " " + min2 + " " + station2);
                        if(car1 == null) {
                            buffer.append("도착 정보 없음");
                        } else {
                            buffer.append("첫번째 차량 도착 정보\n");
                            buffer.append("차량 번호 : " + car1 + " \n");
                            buffer.append("남은 시간 : " + min1 + " 분 \n");
                            buffer.append("남은 구간 : " + station1 + "정거장\n");
                        }
                        // 두번째 도착 차량은 null이 아닐 경우에만 출력
                        if(car2 != null) {
                            buffer.append("-------------------------\n");
                            buffer.append("두번째 차량 도착 정보\n");
                            buffer.append("차량 번호 : " + car2 + " \n");
                            buffer.append("남은 시간 : " + min2 + "분 \n");
                            buffer.append("남은 구간 : " + station2 + "정거장 \n");
                        }
                        xmlShowInfo.setText(buffer.toString());
                    }
                });
            }
        }).start();
    }
 
    //정류소명을 입력하면 정류장 ID를 돌려줌
    /*
     * 오퍼레이션 1
     * 정류소명, 정류소ARS번호를 기준으로 정류소ID, 정류소명, GPS좌표, 정류소구분(일반, 마을)을
     * 조회하는 정류소정보 조회 서비스
     */
    public void getStationId(String station) {
        String stationUrl = endPoint + "/busStop?arsno=" + station + "&serviceKey=" + key;
        Log.d(TAG, "정류장명 -> 정류장Id : " + stationUrl);
 
        try {
            setUrlNParser(stationUrl);
 
            while (eventType != XmlPullParser.END_DOCUMENT) {
                switch (eventType) {
                    case XmlPullParser.START_DOCUMENT:
                        break;
                    case XmlPullParser.START_TAG:
                        tag = xpp.getName();
 
                        if (tag.equals("item")) ; //첫번째 검색 결과
                        else if (tag.equals("bstopId")) {
                            xpp.next();
                            stationId = xpp.getText();
                        } else if (tag.equals("bstopArsno")) ;
                        else if (tag.equals("bstopNm")) ;
                        else if (tag.equals("gpsX")) ;
                        else if (tag.equals("gpsY")) ;
                        else if (tag.equals("stoptype")) ;
                        break;
                    case XmlPullParser.TEXT:
                        break;
                    case XmlPullParser.END_TAG:
                        tag = xpp.getName();
                        if (tag.equals("item")); // 첫번째 검색 결과 종료.. 줄바꿈
                        break;
                } //end of switch~case
 
                eventType = xpp.next();
            } //end of while
        } catch (Exception e) {
            e.printStackTrace();
        }
        //return buffer.toString(); //정류장 이름에 해당하는 id를 넘겨줌
    }
 
    //버스 번호를 입력하면 버스 ID를 돌려줌
    /*
     * 오퍼레이션 2
     * 노선ID, 노선번호를 기준으로 버스종류, 회사이름, 출/도착지, 첫/막차시간, 배차간격을 조회하는 노선정보 조회 서비스
     */
    public void getBusId(String busNum) {
        String busNumUrl = endPoint + "/busInfo?lineno=" + busNum + "&serviceKey=" + key;
        Log.d(TAG,"버스번호 -> 버스id : " + busNumUrl);
 
        try {
            setUrlNParser(busNumUrl);
 
            while (eventType != XmlPullParser.END_DOCUMENT) {
                switch (eventType) {
                    case XmlPullParser.START_DOCUMENT:
                        break;
                    case XmlPullParser.START_TAG:
                        tag = xpp.getName();
 
                        if (tag.equals("item")) ; //첫번째 검색 결과
                        else if (tag.equals("lineId")) {
                            xpp.next();
                            busNumId = xpp.getText();
                        }
                        else if (tag.equals("buslinenum")) ;
                        else if (tag.equals("bustype")) ;
                        else if (tag.equals("companyid")) ;
                        else if (tag.equals("endpoint")) ;
                        else if (tag.equals("stoptype")) ;
                        else if (tag.equals("firsttime")) ;
                        else if (tag.equals("endtime")) ;
                        else if (tag.equals("headway")) ;
                        else if (tag.equals("headwayNorm")) ;
                        else if (tag.equals("headwayPeak")) ;
                        else if (tag.equals("headwayHoli")) ;
                        break;
                    case XmlPullParser.TEXT:
                        break;
                    case XmlPullParser.END_TAG:
                        tag = xpp.getName();
                        if (tag.equals("item")); // 첫번째 검색 결과 종료.. 줄바꿈
                        break;
                } //end of switch~case
                eventType = xpp.next();
            } //end of while
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    /*
     * 오퍼레이션 5
     * 정류소 ID, 노선 ID를 기준으로 실시간 도착정보인 차량번호, 남은 도착시간, 남은 정류장 수
     * 저상버스유무를 인접버스 두 대에 대해 조회하는 노선 정류소 도착정보 조회 서비스
     */
    public void userWant(String busNumId, String stationId) {
        String dataUrl = endPoint + "/busStopArr?bstopid=" + stationId + "&lineid=" + busNumId + "&serviceKey=" + key;
        Log.d(TAG, dataUrl);
 
        try {
            setUrlNParser(dataUrl);
 
            while (eventType != XmlPullParser.END_DOCUMENT) {
                switch (eventType) {
                    case XmlPullParser.START_DOCUMENT:
                        break;
                    case XmlPullParser.START_TAG:
                        tag = xpp.getName();
 
                        if (tag.equals("item")) ; //첫번째 검색 결과
                        else if (tag.equals("carNo1")) {
                            xpp.next();
                            car1 = xpp.getText();
                        } else if (tag.equals("min1")) {
                            xpp.next();
                            min1 = xpp.getText();
                        } else if (tag.equals("station1")) {
                            xpp.next();
                            station1 = xpp.getText();
                        } else if (tag.equals("carNo2")) {
                            xpp.next();
                            car2 = xpp.getText();
                        } else if (tag.equals("min2")) {
                            xpp.next();
                            min2 = xpp.getText();
                        } else if (tag.equals("station2")) {
                            xpp.next();
                            station2 = xpp.getText();
                        }else if (tag.equals("bstopId")) ;
                        else if (tag.equals("nodeNm")) ;
                        else if (tag.equals("companyid")) ;
                        else if (tag.equals("gpsX")) ;
                        else if (tag.equals("gpsY")) ;
                        else if (tag.equals("bustype")) ;
                        else if (tag.equals("lineid")) ;
                        else if (tag.equals("bstopidx")) ;
                        break;
                    case XmlPullParser.TEXT:
                        break;
                    case XmlPullParser.END_TAG:
                        tag = xpp.getName();
                        if (tag.equals("item")); // 첫번째 검색 결과 종료.. 줄바꿈
                        break;
                } //end of switch~case
                eventType = xpp.next();
            } //end of while
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    // 사용자가 입력한 값을 검사하는 함수
    public boolean exmineData() {
 
        // 사용자가 하나 이상의 값을 입력하지 않은 경우
        if (busNum.equals(""|| stationArsno.equals("")) {
            Toast.makeText(this"값을 입력해주세요!", Toast.LENGTH_SHORT).show();
            return true;
        }
 
        //String[] arr = new String[] {busNum, stationArsno};
        String regExp = "([0-9])"// 입력값은 반드시 숫자여야하므로 정규 표현식으로 설정
        Pattern pattern_symbol = Pattern.compile(regExp);
 
        //버스 번호 유효성 검사
        Matcher matcher_busNum = pattern_symbol.matcher(busNum); // 입력값이 유효하다면 true return
        if(matcher_busNum.find() == false) {
            Toast.makeText(this"버스 번호를 다시 입력해주세요!", Toast.LENGTH_SHORT).show();
            return true;
        }
        //정류장 번호 유효성 검사
        Matcher matcher_stationArsno = pattern_symbol.matcher(stationArsno); // 입력값이 유효하다면 true return
        if(matcher_stationArsno.find() == false) {
            Toast.makeText(this"정류장 번호를 다시 입력해주세요!", Toast.LENGTH_SHORT).show();
            return true;
        }
 
        return false//모든 값이 정상
    }
 
    // Url, XmlPullParser 객체 생성 및 초기화
    public void setUrlNParser(String quary) {
        try {
            url = new URL(quary); //문자열로 된 요청 url을 URL객체로 생성
            is = url.openStream();
 
            factory = XmlPullParserFactory.newInstance();
            xpp = factory.newPullParser();
            xpp.setInput(new InputStreamReader(is, "UTF-8")); //inputStream으로부터 xml입력받기
 
            xpp.next();
            eventType = xpp.getEventType();
        } catch (Exception e) {
 
        }
 
    }
 
    // UI ID 얻는 함수
    public void getXmlId() {
        xmlBusNum = findViewById(R.id.busNum);
        xmlStationArsno = findViewById(R.id.stationArsno);
        xmlShowInfo = findViewById(R.id.showInfo);
    }
}
 
cs


반응형

'Android' 카테고리의 다른 글

[Android] 전체화면 전환  (0) 2018.08.17
[Android] 피아노 어플만들기  (0) 2018.08.17

+ Recent posts