본문 바로가기

Etc/Android

[Android] 공공데이터 파싱후 T-Map지도에 마커 구현하기

반응형
 

[Android]공공데이터 '민방위 대피소정보 서비스' API 파싱하기

더보기 [👨‍🎓학교 수업👨‍🎓/[3-2]Android] - [Android] T-Map API을 사용하여 지도 띄워보기 [Android] T-Map API을 사용하여 지도 띄워보기 [👨‍🎓학교 수업👨‍🎓/[3-2]Android] - [Android]..

sungmin.dev

 

[Android] T-Map API을 사용하여 지도 띄워보기

[👨‍🎓학교 수업👨‍🎓/[3-2]Android] - [Android] 자바로 안드로이드 앱 다음 지도 API사용하여 지도 띄워보기 [Android] 자바로 안드로이드 앱 다음 지도 API사용하여 지도 띄워보기 다음지도 API 키 발..

sungmin.dev

본 글은 NY님의 글(http://blog.naver.com/PostView.nhn?blogId=yandul83&logNo=220436066801)을 참고하여 작성하였습니다.

이전 글을 보면 공공데이터인 '민방위 대피소 정보 서비스'를 파싱 하는 것을 확인할 수 있다.

현재 나는 충남도청 공공데이터 서포터즈 1기로 활동 중이며, 위의 공공데이터를 활용하여 모바일 SW 프로젝트 수업의
프로젝트를 진행하고 있다.

공공데이터를 파싱한후 1주일 동안 지도에 마커를 띄우기 위해 많은 삽질을 하였고 T-Map의 자료가 많이 없어
직접 작성하기로 하였다.

우선 기본적인 개발환경은 다음과 같다.

개발 언어 : Java 12.0.2

개발 툴 : Android Studio 3.5.2

지도 : T-Map (http://tmapapi.sktelecom.com/index.html)

공공 데이터 : 민방위 대피소 정보 서비스 (https://www.data.go.kr/dataset/3038747/openapi.do?mypageFlag=Y)

이 글에서는 공공데이터 파싱 하는 부분은 제외하고 글을 작성하려고 한다.
파싱 부분은 이전 글을 참고하기 바란다.

1. 공공데이터 파싱을 위한 Class 만들기


가장 먼저 해당 데이터를 사용하기 위해서는 공공데이터 포털에서 제공하는 기술문서를 확인을 해야 한다.
그 이유는 데이터마다 tag값이 다르고 인터넷에 제공된 코드를 따라 하다 보면 tag값이 달라져서 파싱이 안 되는 경우가 많이 있기 때문이다.

우선 내가 필요한 대피소 이름, 위도, 경도를 불러오기 위한 클래스를 만든다.

MapPoint.java

public class MapPoint {
    private String Name; //대피소 이름
    private double  latitude; //위도
    private  double longitude; //경도

    public MapPoint() {
        super();
    }

    public  MapPoint(String Name, double latitude, double longitude) {
        this.Name = Name;
        this.latitude = latitude;
        this.longitude = longitude;
    }

    public String getName() { //대피소 이름
        return Name;
    }

    public void setName(String Name){
        this.Name = Name;
    }

    public double getLatitude() { //위도
        return latitude;
    }

    public  void setLatitude(double latitude){
        this.latitude = latitude;
    }

    public double getLongitude() { //경도
        return longitude;
    }

    public void setLongitude(double longitude) {
        this.longitude = longitude;
    }
}

 

2. API 파싱 Class 클래스 만들기


공공데이터를 마커로 찍기 위해선 ArrayList를 통해 배열에 각각의 데이터들을 파싱 해 추가해주는 것으로 구현을 하였다.
또한 파싱 된 결과가 추가될 경우 true값으로 변경 해주며 값이 들어간것을 확인한후 false값으로 바꿔주어 파싱된 결과를 확인하였다.

해당 데이터는 json과 xml을 모두 지원하는데 나는 xml으로 파싱 하여 마커를 찍어 주었다.

ShelterApi.java

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.BufferedInputStream;
import java.net.URL;
import java.util.ArrayList;

public class ShelterApi {
    private static String ServiceKey = "API키"; //공공데이터 사이트를 통해 발급 받은 API키
    public ShelterApi() {
        try {
            apiParserSearch();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public ArrayList<MapPoint> apiParserSearch() throws Exception {
        URL url = new URL(getURLParam(null));

        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        factory.setNamespaceAware(true);
        XmlPullParser xpp = factory.newPullParser();
        BufferedInputStream bis = new BufferedInputStream(url.openStream());
        xpp.setInput(bis, "utf-8");

        String tag = null;
        int event_type = xpp.getEventType();

        ArrayList<MapPoint> mapPoint = new ArrayList<MapPoint>();

        String facility_name = null, longitude= null,latitude=null;
        boolean bfacility_name = false, blatitude = false, blongitude = false;

        while (event_type != XmlPullParser.END_DOCUMENT) {
            if (event_type == XmlPullParser.START_TAG) {
                tag = xpp.getName();
                if(tag.equals("facility_name")) {
                    bfacility_name = true;
                }
                if(tag.equals("latitude")) {
                    blatitude = true;
                }
                if(tag.equals("longitude")){
                    blongitude = true;
                }
            } else if (event_type == XmlPullParser.TEXT) {
                if(bfacility_name == true){
                    facility_name = xpp.getText();
                    bfacility_name = false;
                } else if(blatitude == true){
                    latitude = xpp.getText();
                    blatitude = false;
                }else if(blongitude ==true){
                    longitude = xpp.getText();
                    blongitude = false;
                }
            } else if (event_type == XmlPullParser.END_TAG) {
                tag = xpp.getName();
                if (tag.equals("row")) {
                    MapPoint entity = new MapPoint();
                    entity.setName(facility_name);
                    entity.setLatitude(Double.valueOf(latitude));
                    entity.setLongitude(Double.valueOf(longitude));
                    mapPoint.add(entity);
                    System.out.println(mapPoint.size());
                }
            }
            event_type = xpp.next();
        }
        System.out.println(mapPoint.size());

        return mapPoint;
    }

    private String getURLParam(String search){
        String url = "http://apis.data.go.kr/1741000/CivilDefenseShelter2/getCivilDefenseShelterList?ServiceKey=" + ServiceKey + "&type=xml&pageNo=1&numOfRows=300&flag=Y";
        return url;
    }

    public static void main(String[] args) {
        new ShelterApi();
    }
}

 

또한 개발 문서를 보면 요청 메세지의 defailt 값들은 type = xml, pageNo = 1, numOfRows = 10인 것을 확인할 수 있다. 이 말은 url 부분의 target 값을 변경 안 해주면 xml 형식으로 1페이지에 10개 정도의 데이터만 출력되기 때문에
target 값을 변경해 주어야 한다. (위의 코드는 xml형식으로 파싱 하여 300개의 데이터를 1페이지에 출력하고 있다.)

개발문서에 적힌 내용

 

3. 지도에 파싱 한 결과 마커로 표시하기


그럼 이제 파싱한 결과를 마커로 표시해주면 된다.

우선 다중 마커식으로 구현을 해야 하기 때문에 파싱한 결과를 for문을 통해 구현을 하였다.

MainActivity.java

package dev.sungmin.Shelter;

        import androidx.appcompat.app.AppCompatActivity;
        import android.os.Bundle;
        import android.os.StrictMode;
        import android.widget.LinearLayout;
        import android.location.Location;

        import com.skt.Tmap.TMapGpsManager;
        import com.skt.Tmap.TMapView;
        import com.skt.Tmap.TMapMarkerItem;
        import com.skt.Tmap.TMapPoint;

        import java.util.ArrayList;


public class MainActivity extends AppCompatActivity implements TMapGpsManager.onLocationChangedCallback {

    private boolean TrackingMode = true;
    private TMapView tMapView = null;
    private TMapGpsManager tmapgps = null;
    private static String TMapAPIKey = "앱";

    @Override
    public void onLocationChange(Location location) {
        if (TrackingMode) {
            tMapView.setLocationPoint(location.getLongitude(), location.getLatitude());
        }
    }

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

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);


        LinearLayout linearLayoutTmap = (LinearLayout) findViewById(R.id.linearLayoutTmap);
        tMapView = new TMapView(this);
        tMapView.setHttpsMode(true);
        //발급 받은 API키  보안상 문제로 인하여 깃허브 커밋시 지워서 커밋할것!
        tMapView.setSKTMapApiKey(TMapAPIKey);
        linearLayoutTmap.addView(tMapView);

        setUpMap();

        /*현재 보는 방향으로 설정*/
        tMapView.setCompassMode(true);

        /*현 위치 아이콘 설정*/
        tMapView.setIconVisibility(true);

        tMapView.setZoomLevel(15);
        tMapView.setMapType(TMapView.MAPTYPE_STANDARD);
        tMapView.setLanguage(TMapView.LANGUAGE_KOREAN);

        tmapgps = new TMapGpsManager(MainActivity.this);
        tmapgps.setMinTime(1000);
        tmapgps.setMinDistance(5);
        tmapgps.setProvider(tmapgps.NETWORK_PROVIDER); //네트워크에서 가져옴
        tmapgps.OpenGps(); //가상으로 테스트시 이부분은 지워주어야 오류가 없음

        tMapView.setTrackingMode(true);
        tMapView.setSightVisible(true);
    }


    private void setUpMap() {
        ShelterApi parser = new ShelterApi();
        ArrayList<MapPoint> mapPoint = new ArrayList<MapPoint>();
        try {
            mapPoint = parser.apiParserSearch();
        } catch (Exception e) {
            e.printStackTrace();
        }
        for (int i = 0; i < mapPoint.size(); i++) {
            for (MapPoint entity : mapPoint) {
                TMapPoint point = new TMapPoint(mapPoint.get(i).getLatitude(), mapPoint.get(i).getLongitude());
                TMapMarkerItem markerItem1 = new TMapMarkerItem();

                markerItem1.setPosition(0.5f, 1.0f);
                markerItem1.setTMapPoint(point);
                markerItem1.setName(entity.getName());
                tMapView.setCenterPoint(mapPoint.get(i).getLongitude(), mapPoint.get(i).getLatitude());
                tMapView.addMarkerItem("markerItem1" + i, markerItem1);
            }
        }
    }
}

 

* 결과


위의 코드를 통해 구현 시 아래와 같은 사진으로 구동됨을 확인할 수 있다.

구현 결과 1
구현 결과 2

반응형


Calendar
«   2024/04   »
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
Visits
Today
Yesterday