Tech. Forum 개발자들을 위한 정보 공유의 장입니다
닫기

Tech.Forum

안드로이드 map 마크 클러스터링 문의

#1

안녕하세요
이번에 TMap API를 사용하여 충전소 관련 프로젝트를 하고 있습니다.

지금 저희 어플에서 마크만 최소 1,000개 최대 14,000개를 뿌려 줄 예정입니다.
(현재 개발에서는 1,000)개만 나타나고 있습니다.

지도를 줌인/아웃하는 과정에서 마크 클러스터링 관련 기능을 구현하고자 합니다.
tmapview.setEnableClustering(true);
item1.setEnableClustering(true);

이 두가지 추가하였는데,
클러스터링 기능이 구현되지 않습니다.

이와 관련하여 샘플이나 예제 알려주실 수 있으실까요?
현재 저희 어플 소스 추가하여 올려드립니다.
확인 부탁드립니다.

=======================================================================
package com.example.testapp;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PointF;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

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

import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;

import java.util.ArrayList;
import java.util.logging.LogManager;

public class TMap extends AppCompatActivity implements TMapView.OnClickListenerCallback {

private Context mContext = null;
private boolean m_bTrackingMode = true;

private TMapGpsManager tmapgps = null;
private TMapView tmapview = null;
private static String mApiKey = "46bf9f8e-4a09-4a75-a4d6-038e0f73547b";
private static int mMarkerID;

private ArrayList<TMapPoint> m_tmapPoint = new ArrayList<TMapPoint>();
private ArrayList<String> mArrayMarkerID = new ArrayList<String>();
private ArrayList<MapPoint> m_mapPoint = new ArrayList<MapPoint>();


private Button target;

@Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_tmap_view);
    setGps();

        mContext = this;

        LinearLayout linearLayout = (LinearLayout) findViewById(R.id.mapview);
        tmapview = new TMapView(this);
        linearLayout.addView(tmapview);
        tmapview.setSKTMapApiKey(mApiKey);

        //addPoint();

        //현재 보는 방향
        tmapview.setCompassMode(true);

        //현위치 아이콘표시
        tmapview.setIconVisibility(true);//현재위치로 표시될 아이콘을 표시할지 여부를 설정합니다.
        //tmapview.setIconVisibility(true);

        //줌레벨
        tmapview.setZoomLevel(10);
        tmapview.setMapType(TMapView.MAPTYPE_STANDARD);
        tmapview.setLanguage(TMapView.LANGUAGE_KOREAN);
        tmapview.setIconVisibility(true);
        tmapview.setCompassMode(true);

        //화면중심을 단말의 현재위치로 이동시켜주는 트래킹 모드로 설정
        tmapview.setTrackingMode(true);
        tmapview.setHttpsMode(true);

        tmapgps = new TMapGpsManager(TMap.this);
        tmapgps.setProvider(TMapGpsManager.GPS_PROVIDER);  //GPS로 현 위치를 잡음
        tmapgps.setMinTime(1000);
        tmapgps.setMinDistance(5);

        tmapgps.OpenGps();

        //화면중심을 단말의 현재위치로 이동
        tmapview.setTrackingMode(true);
        tmapview.setSightVisible(true);
        tmapview.setEnableClustering(true);


        showMarkerPoint();

// //풍선에서 우측 버튼 클릭 시 할 행동
// tmapview.setOnCalloutRightButtonClickListener(new TMapView.OnCalloutRightButtonClickCallback() {
// @Override
// public void onCalloutRightButton(TMapMarkerItem tMapMarkerItem) {
// Toast.makeText(TMap.this, “클릭”, Toast.LENGTH_SHORT).show();
// }
// });

    target = (Button)this.findViewById(R.id.Navi);

    target.setOnClickListener(new Button.OnClickListener() {
        public void onClick(View view) {
            Intent intent = new Intent(getApplicationContext(), Navigation.class);
            startActivity(intent);
        }
    });
    }

    public void addPoint(){ //핀을 꼽을 포인트들을 배열에 add

        ArrayList<EV_DTO> EV_List = getIntent().getParcelableArrayListExtra("ev_data");
        int cnt = 0;

        for(EV_DTO ev : EV_List){
            m_mapPoint.add(new MapPoint(ev.getStatNm(),ev.getLat(),ev.getLng()));
       }

// //m_mapPoint.add(new MapPoint(“양동시장”,35.152392,126.903015));
}

    //마커찍는거 빨간색 포인트
public void showMarkerPoint(){
    ArrayList<EV_DTO> EV_List = getIntent().getParcelableArrayListExtra("ev_data");


    for(EV_DTO ev : EV_List){
        int cnt = 0;
        TMapPoint point = new TMapPoint(ev.getLat(),ev.getLng());
        TMapMarkerItem item1 = new TMapMarkerItem();
        Bitmap bitmap =  BitmapFactory.decodeResource(mContext.getResources(),R.mipmap.marker);    //poi_dot은 지도에 꼽을 빨간 핀 이미지
        cnt++;

        item1.setTMapPoint(point);
        item1.setPosition(0.5f, 0.5f);
        item1.setPosition(0.5f,1.0f);
        item1.setName(ev.getStatNm());
        item1.setIcon(bitmap);
        item1.setVisible(item1.VISIBLE);    //마커의 표시 여부
        item1.setCanShowCallout(true);

        boolean result = item1.getCanShowCallout();
        item1.setCalloutTitle(ev.getStatNm());
        item1.setCalloutSubTitle(ev.getAddr());


        item1.setAutoCalloutVisible(true);  //풍선뷰 자동 활성화
        item1.setEnableClustering(true);    //마커의 클러스터링 유무 설정

        String strID = ev.getStatNm();

        tmapview.addMarkerItem(strID, item1);
        mArrayMarkerID.add(strID);

    }
}   private final LocationListener mLocationListener = new LocationListener() {
    public void onLocationChanged(Location location) {

        if (location != null) {
            double latitude = location.getLatitude();
            double longitude = location.getLongitude();
            tmapview.setLocationPoint(longitude, latitude);
            tmapview.setCenterPoint(longitude, latitude);

        }
    }

    public void onProviderDisabled(String provider) {
    }

    public void onProviderEnabled(String provider) {
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {
    }
};

public void setGps() {
    final LocationManager lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}, 1);
    }
    lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, // 등록할 위치제공자(실내에선 NETWORK_PROVIDER 권장)
            1000, // 통지사이의 최소 시간간격 (miliSecond)
            1, // 통지사이의 최소 변경거리 (m)
            mLocationListener);
}
@Override
public boolean onPressEvent(ArrayList<TMapMarkerItem> arrayList, ArrayList<TMapPOIItem> arrayList1, TMapPoint tMapPoint, PointF pointF) {
    return false;
}

@Override
public boolean onPressUpEvent(ArrayList<TMapMarkerItem> arrayList, ArrayList<TMapPOIItem> arrayList1, TMapPoint tMapPoint, PointF pointF) {
    return false;
}

}

0 Likes

#2

안녕하세요.

T map API 운영담당자입니다.

현재 테스트 결과 TmapView.setEnableClustering()와 TMapMarkerItem.setEnableClustering()을
둘다 true로 설정시 마크 클러스터링기능이 정상 동작 하였습니다.
아래의 테스트한 예시를 참고하시면 도움이 되실겁니다.


EX)
for (double x = 126.983045; x <= 126.984045; x += 0.0008) {
for (double y = 37.570194; y <= 37.571194; y += 0.0008) {

            TMapPoint point = new TMapPoint(y,x);
            TMapMarkerItem markerItem1 = new TMapMarkerItem();
            markerItem1.setIcon(bitmap); // 마커 아이콘 지정
            markerItem1.setPosition(0.5f, 1.0f); // 마커의 중심점을 설정
            markerItem1.setTMapPoint( point ); // 마커의 좌표 지정
            markerItem1.setName("SKT타워"); // 마커의 타이틀 지정
            markerItem1.setEnableClustering(true); // 클러스터링 사용
            strID=String.format("pmarker%d", strN++); // 마커ID 재지정
            mMapView.addMarkerItem(strID, markerItem1); // 지도에 마커 추가
        }
    }

mMapView.setCenterPoint( 126.985302, 37.570841 );

    mMapView.setEnableClustering(true);

    for (double x = 126.985045; x <= 126.987045; x += 0.0008) {
        for (double y = 37.572194; y <= 37.574194; y += 0.0008) {

            TMapPoint point = new TMapPoint(y,x);
            TMapMarkerItem markerItem1 = new TMapMarkerItem();
            markerItem1.setIcon(bitmap); // 마커 아이콘 지정
            markerItem1.setPosition(0.5f, 1.0f); // 마커의 중심점을 설정
            markerItem1.setTMapPoint( point ); // 마커의 좌표 지정
            markerItem1.setName("SKT타워"); // 마커의 타이틀 지정
            markerItem1.setEnableClustering(true);

            strID=String.format("pmarker%d", strN++);
            mMapView.addMarkerItem(strID, markerItem1); // 지도에 마커 추가
        }
    }

감사합니다.

0 Likes

#3

package com.example.testapp;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PointF;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

import com.example.testapp.model.EV_DTO;
import com.skt.Tmap.TMapGpsManager;
import com.skt.Tmap.TMapMarkerItem;
import com.skt.Tmap.TMapPOIItem;
import com.skt.Tmap.TMapPoint;
import com.skt.Tmap.TMapView;

import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;

import java.util.ArrayList;

public class TMap extends AppCompatActivity implements TMapView.OnClickListenerCallback {

private Context mContext = null;
private boolean m_bTrackingMode = true;

private TMapGpsManager tmapgps = null;
private TMapView tmapview = null;
private static String mApiKey = "46bf9f8e-4a09-4a75-a4d6-038e0f73547b";
private static int mMarkerID;

private ArrayList<TMapPoint> m_tmapPoint = new ArrayList<TMapPoint>();
private ArrayList<String> mArrayMarkerID = new ArrayList<String>();
private ArrayList<MapPoint> m_mapPoint = new ArrayList<MapPoint>();
ArrayList<EV_DTO> EV_List;
private Button target;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_tmap_view);
    setGps();
    mContext = this;

    LinearLayout linearLayout = (LinearLayout) findViewById(R.id.mapview);
    tmapview = new TMapView(this);
    linearLayout.addView(tmapview);
    tmapview.setSKTMapApiKey(mApiKey);

    //addPoint();

    //현재 보는 방향
    tmapview.setCompassMode(true);

    //현위치 아이콘표시
    tmapview.setIconVisibility(true);//현재위치로 표시될 아이콘을 표시할지 여부를 설정합니다.
    //tmapview.setIconVisibility(true);

    //줌레벨
    tmapview.setZoomLevel(10);
    tmapview.setMapType(TMapView.MAPTYPE_STANDARD);
    tmapview.setLanguage(TMapView.LANGUAGE_KOREAN);
    tmapview.setIconVisibility(true);
    tmapview.setCompassMode(true);

    //화면중심을 단말의 현재위치로 이동시켜주는 트래킹 모드로 설정
    tmapview.setTrackingMode(true);
    tmapview.setHttpsMode(true);

    tmapgps = new TMapGpsManager(TMap.this);
    tmapgps.setProvider(TMapGpsManager.GPS_PROVIDER);  //GPS로 현 위치를 잡음
    tmapgps.setMinTime(1000);
    tmapgps.setMinDistance(5);

    tmapgps.OpenGps();

    //화면중심을 단말의 현재위치로 이동
    tmapview.setTrackingMode(true);
    tmapview.setSightVisible(true);

    showMarkerPoint();
    tmapview.setEnableClustering(true);

// //풍선에서 우측 버튼 클릭 시 할 행동
// tmapview.setOnCalloutRightButtonClickListener(new TMapView.OnCalloutRightButtonClickCallback() {
// @Override
// public void onCalloutRightButton(TMapMarkerItem tMapMarkerItem) {
// Toast.makeText(TMap.this, “클릭”, Toast.LENGTH_SHORT).show();
// }
// });

    target = (Button) this.findViewById(R.id.Navi);
    target.setOnClickListener(new Button.OnClickListener() {
        public void onClick(View view) {
            Intent intent = new Intent(getApplicationContext(), Navigation.class);
            startActivity(intent);
        }
    });
}

// public void addPoint(){ //핀을 꼽을 포인트들을 배열에 add
//
// ArrayList<EV_DTO> EV_List = getIntent().getParcelableArrayListExtra(“ev_data”);
// int cnt = 0;
//
// for(EV_DTO ev : EV_List){
// m_mapPoint.add(new MapPoint(ev.getStatNm(),ev.getLat(),ev.getLng()));
// }
//
//// //m_mapPoint.add(new MapPoint(“양동시장”,35.152392,126.903015));
// }

//마커찍는거 빨간색 포인트
public void showMarkerPoint() {
    EV_List = (ArrayList<EV_DTO>) ShareData.getInstance().get("data");
    int cnt = 0;
    for (EV_DTO ev : EV_List) {
        TMapPoint point = new TMapPoint(ev.getLat(), ev.getLng());
        TMapMarkerItem item1 = new TMapMarkerItem();
        Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.marker);    //poi_dot은 지도에 꼽을 빨간 핀 이미지

        item1.setTMapPoint(point);
        item1.setPosition(0.5f, 0.5f);  //마커 위치 설정
        item1.setName(ev.getStatNm());
        item1.setIcon(bitmap);
        item1.setVisible(item1.VISIBLE);    //마커의 표시 여부


        //bitmap = BitmapFactory.decodeResource(mContext.getResources(),R.mipmap.marker);

        item1.setCalloutTitle(ev.getStatNm());
        //item1.setCalloutSubTitle(ev.getS);
        item1.setCanShowCallout(true);
        item1.setAutoCalloutVisible(false);

        //===================클러스터링

        item1.setEnableClustering(true);    //마커의 클러스터링 유무 설정
        System.out.println(item1.getEnableClustering());

        //Bitmap bitmap_i = BitmapFactory.decodeResource(mContext.getResources(),R.mipmap.i_go);

        //item1.setCalloutRightButtonImage(bitmap_i);

        String strID = ev.getStatNm();

        tmapview.addMarkerItem(strID, item1);
        mArrayMarkerID.add(strID);

    }

// tmapview.setEnableClustering(true);
}

private final LocationListener mLocationListener = new LocationListener() {
    public void onLocationChanged(Location location) {

        if (location != null) {
            double latitude = location.getLatitude();
            double longitude = location.getLongitude();
            tmapview.setLocationPoint(longitude, latitude);
            tmapview.setCenterPoint(longitude, latitude);

        }
    }

    public void onProviderDisabled(String provider) {
    }

    public void onProviderEnabled(String provider) {
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {
    }
};

public void setGps() {
    final LocationManager lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}, 1);
    }
    lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, // 등록할 위치제공자(실내에선 NETWORK_PROVIDER 권장)
            1000, // 통지사이의 최소 시간간격 (miliSecond)
            1, // 통지사이의 최소 변경거리 (m)
            mLocationListener);
}

@Override
public boolean onPressEvent(ArrayList<TMapMarkerItem> arrayList, ArrayList<TMapPOIItem> arrayList1, TMapPoint tMapPoint, PointF pointF) {
    return false;
}

@Override
public boolean onPressUpEvent(ArrayList<TMapMarkerItem> arrayList, ArrayList<TMapPOIItem> arrayList1, TMapPoint tMapPoint, PointF pointF) {
    return false;
}

}

==================================================
저희 소스 코드 수정하여 올려드립니다.
충전소 데이터는 13075개입니다.

tmapview.setEnableClustering(true);
item1.setEnableClustering(true);
두 개 다 true로 설정하였는데
검은색화면에서 Waiting for a blocking GC ProfileSaver 오류가 뜹니다.
어떻게 해결해야 하나요?

여기서 tmapview.setEnableClustering(true);를 주석처리하면 앱이 정상작동합니다.
해결방법을 알려주세요ㅠㅠ

0 Likes

#4

안녕하세요.

T map API 운영담당자 입니다.

문의하신 내용과 같이 과도한 갯수의 마커를 생성후 클러스터링 기능을 사용하시게 되면,
메모리 문제와 같은 여러 문제로 인해 정상적인 동작이 어려워 발생한 오류로 보여집니다.
적당한량의 마커를 생성하시고 사용하시면 정상적으로 동작하게 됩니다.

감사합니다.

0 Likes