카테고리 없음

공공데이터를 이용한 앱 만들어보기(4) - DB에 넣어보기

카멜레온개발자 2021. 12. 1. 20:49

수신 받은 데이터를 DB에 한번 넣어보려고 한다

 

1. 화면은 다음과 같이 정리했다.

더보기
<?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"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnRequest"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="요청하기" />

        <Button
            android:id="@+id/btnStationInsert"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="DB INSERT" />
    </LinearLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvStation"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

2. 버튼을 누르면

  1) DB가 없으면 DB 생성(createDatabase 함수)

  2) 테이블이 없으면 테이블 생성(createTable 함수)

  3) 1개의 데이터만 요청한다. (총 갯수만 알아낼 목적으로 - RequestItemCount()함수)

더보기
        Button btn2 = findViewById(R.id.btnStationInsert);
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                createDatabase(DATABASE_NAME); //데이터베이스 생성
                createTable();                 //테이블 생성

                StringRequest request = new StringRequest(
                        Request.Method.GET,
                        "http://apis.data.go.kr/6260000/BusanBIMS/busStopList?serviceKey=___________&pageNo=1&numOfRows=1",
                        new Response.Listener<String>() {
                            @Override
                            public void onResponse(String response) {
                                RequestItemCount(response);
                            }
                        },
                        new Response.ErrorListener() {
                            @Override
                            public void onErrorResponse(VolleyError error) {
                                Log.d(TAG, "onErrorResponse : " + error.toString());
                            }
                        }
                ){
                    //요청 파라미터를 처리하는 메소드
                    @Nullable
                    @Override
                    protected Map<String, String> getParams() throws AuthFailureError {
                        //요청 객체가 하나 만들어짐
                        Map<String, String> params = new HashMap<String, String>();
                        //요청 큐에 넣어주면 된다

                        return super.getParams();
                    }
                };
                request.setShouldCache(false);
                requestQueue.add(request);
            }
        });
public void createDatabase(String databaseName){
    if(database == null){
        try{
            database = openOrCreateDatabase(databaseName, MODE_PRIVATE, null);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}
public void createTable(){
    try{
        if(database == null) return;
        if(adapter == null)  return;
        String sql = "create table if not exists station "
                   + "(bstopid INTEGER primary key, bstopnm varchar, arsno INTEGER, gpsx double, gpsy  double, stoptype varchar, version INTEGER)";
        database.execSQL(sql);
    }
    catch(Exception e){
        e.printStackTrace();
    }
}

3. 이 데이터의 경우 1개만 요청해도 총 갯수정보가 들어 있으므로 그 정보를 이용해서 모든 데이터를 다시 요청한다

('totalCount' 태그)

  1) 총 데이터 갯수를 알아내고

  2) 1000개씩 분할해서 요청한다(갯수는 조정가능)

더보기
private void RequestItemCount(String response)
{
    int count = ParseStationCount(response);
    int div = 1000;

    int pages = count / div;
    if(count % div > 0)
        pages += 1;

    RequestPage(pages, 1, div);
}
private int ParseStationCount(String response){
    String curr_tag = "";
    try {
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        factory.setNamespaceAware(true);
        XmlPullParser xpp = factory.newPullParser();

        xpp.setInput( new StringReader(response) );
        int eventType = xpp.getEventType();
        while (eventType != XmlPullParser.END_DOCUMENT) {
            if(eventType == XmlPullParser.START_DOCUMENT) {
            } else if(eventType == XmlPullParser.START_TAG) {
                curr_tag = xpp.getName();
            } else if(eventType == XmlPullParser.END_TAG) {
                curr_tag = "";
            } else if(eventType == XmlPullParser.TEXT) {
                if(curr_tag.equals("totalCount"))
                    return Integer.parseInt(xpp.getText());
            }
            eventType = xpp.next();
        }

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

    return 0;
}

4. 페이지별 요청은 다음과 같이 구현하고, DB에 insert한다

  (DB insert시에는 낱개로 넣는것보다 Transaction을 이용하는 것이 빠른듯)

더보기
private void RequestPage(int total_page, int index_page, int div){
	String requstStr = "http://apis.data.go.kr/6260000/BusanBIMS/busStopList?serviceKey=________________&pageNo="+index_page+"&numOfRows=" + div;

			StringRequest request = new StringRequest(
			Request.Method.GET,
			requstStr,
			new Response.Listener<String>() {
				@Override
				public void onResponse(String response) {
					ArrayList<Station> list = ParseStatonStr(response);
					insertData(list);

					if(index_page + 1 <= total_page){
						Log.d(TAG, "Progress : " + (index_page + 1) +"/" + total_page);
						RequestPage(total_page, index_page + 1, div);
					}
				}
			},
			new Response.ErrorListener() {
				@Override
				public void onErrorResponse(VolleyError error) {

				}
			})
	{
		//요청 파라미터를 처리하는 메소드
		@Nullable
		@Override
		protected Map<String, String> getParams() throws AuthFailureError {
			//요청 객체가 하나 만들어짐
			Map<String, String> params = new HashMap<String, String>();
			//요청 큐에 넣어주면 된다

			return super.getParams();
		}
	};
	request.setShouldCache(false);
	requestQueue.add(request);
}
public void insertData(ArrayList<Station> list){
	try{
		if(database == null) return;
		if(adapter == null)  return;

		String sql = "";
		String sql_insert = "insert or replace into station (bstopid, bstopnm, arsno, gpsx, gpsy, stoptype, version) values (";
		Station station;
		database.beginTransaction();

		for(int i=0; i<list.size(); ++i)
		{
			sql = list.get(i).values() + ", 1)";
			database.execSQL(sql_insert + sql);
		}

		database.setTransactionSuccessful();

	}
	catch(Exception e){
		e.printStackTrace();
	}
	finally{
		database.endTransaction();
	}
}

 

5. 안드로이드 에뮬레이터를 실행시키고, 버튼을 누르면 다음과 같이 1000개씩 잘 얻어온다

6. 저장된 결과는 다음과같이 저장 가능하다

(안드로이드 스튜디오 Device Explorer > 아래 경로의 DB를 찾아가서 마우스 우클릭 > Save As 메뉴 선택 후 저장)

 

7. 저장된 파일을 Sqlite 뷰어 프로그램으로 열어보면 다음과 같이 나타난다