본문 바로가기
안드로이드

위치 지도에 표시하기

by 희안 2021. 5. 8.

위치 지도에 보여주기

안드로이드는 지도를 앱 화면 안에서 보여줄 수 있도록 맵 프래그먼트가 제공된다. 이 맵 프래그먼트는 구글맵서비스를 이용해서 Google Play Service모듈을 사용한다. 

Google Play Service 라이브러리 사용하기 위해선 메뉴 중 Tools -> SDK Manager 를 눌러 매니저  화면을 불러와서 Appearance&Behavior -> System Setting -> Android SDK -> SDK Tools 를 선택해서 들어간다. 이 안에서 Google Play services 가 설치되어 있는지 확인하고 설치 안되어있으면 Install한다. 

그리고 File -> Project Structure -> Dependencies -> Modules(app) 을 선택하고 Declared Dependencies 아래의 +를 눌러서 Library dependency를 선택한다. 그리고 play-services-maps라이브러리를 찾아 추가해준다. build.gradle에서 추가된걸 확인할 수 있다. 

 

이제 라이브러리 사용설정을 했으니 XML에 맵 프래그먼트를 추가하고, 소스코드에서 내 위치로 지도를 이동시키고, 매니페스트에 지도사용권한을 추가해주고 지도 API키를 추가해주면 된다.. 처음엔 복잡해보인다.

 

XML에 맵 프래그먼트는 아래처럼 class 속성으로 지정해줬다. SupportMapFragment는 예전버전 안드로이드를 지원할 수 있고 MapFragment는 지원필요하지 않을때 사용할 수 있다.

<fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/map"
        class = "com.google.android.gms.maps.SupportMapFragment"/>

 

추가한 class인 SupportMapFragment 클래스 안에는 GoogleMap 객체가 있고 이 위에 지도가 표시된다. 이 객체는 프래그먼트가 초기화 된 후 참조할 수 있는데 레이아웃에 정의한 이 객체를 소스코드에서 참조한 후 getMapAsync()를 호출하면 GoogleMap 객체를 참조할 수 있다. 이 메서드는 비동기 방식으로 처리되어서 콜백객체를 파라미터로 전달한 후 초기화 완료될때 객체안의 onMapReady()함수가 자동으로 호출된다.

만든 함수인 showCurrentLocation()로 전달된 위도 경도값이 LatLng 객체로 지도위에 표시된다. LatLng 객체는 지도 위에 표시할 수 있도록 정의된 객체로 구글맵객체의 animateCamera()를 이용해서 이 위치 중심으로 지도를 보여줄 수 있다. 또 이 메서드는 축척을 지정할 수 있고 1이 멀리서보는것 ~17,18... 커질수록 가까이서 보는게 된다. 

SupportMapFragment mapFragment;
    GoogleMap map;

    MarkerOptions myLocationMarker;

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

        mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(GoogleMap googleMap) {
                Log.d("Map", "지도 준비됨.");
                map = googleMap;

            }
        });

        try {
            MapsInitializer.initialize(this);
        } catch (Exception e) {
            e.printStackTrace();
        }

        Button button = findViewById(R.id.button29);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startLocationService();
            }
        });

        AutoPermissions.Companion.loadAllPermissions(this, 101);
    }

    public void startLocationService() {
        LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        try {
            Location location = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            if (location != null) {
                double latitude = location.getLatitude();
                double longitude = location.getLongitude();
                String message = "최근 위치 -> Latitude : " + latitude + "\nLongitude:" + longitude;

                Log.d("Map", message);
            }

            GPSListener gpsListener = new GPSListener();
            long minTime = 10000;
            float minDistance = 0;

            manager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER,
                    minTime, minDistance, gpsListener);

            Toast.makeText(getApplicationContext(), "내 위치확인 요청함",
                    Toast.LENGTH_SHORT).show();

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

    private void showMyLocationMarker(LatLng curPoint) {
        if (myLocationMarker == null) {
            myLocationMarker = new MarkerOptions();
            myLocationMarker.position(curPoint);
            myLocationMarker.title("● 내 위치\n");
            myLocationMarker.snippet("● GPS로 확인한 위치");
            myLocationMarker.icon(BitmapDescriptorFactory.fromResource(R.drawable.mylocation));
            map.addMarker(myLocationMarker);
        } else {
            myLocationMarker.position(curPoint);
        }
    }

마지막으로는 매니페스트에 여러 정보들을 등록해주어야한다. <uses-feature> 태그는 지도서비스가 OpenGL 기능을 사용할 수 있도록 추가되었고 <application>안의 <meta-data> 태그에 지도 서비스 키값이 들어간다. 

 

구글 API 키 발급받기

http://console.developers.google.com 사이트에 들어간다. 프로젝트를 하나 만들고 API 서비스로 들어간다. 그 중 Maps SDK for Android를 사용하면 된다! 거기서 사용자인증정보 -> 인증정보만들기 -> API 키 선택하면 키를 만들 수 있고 이걸 아까 meta-data 태그안의 value에 집어넣으면 된다.

DexIndexOverflowException 이라는 오류가 표시되는 경우는 앱이 빌드되면서 만들어지는 dex 파일의 크기가 커지면서 생기는 문제인데 이를 해결하기 위해선 MultiDex 설정을 추가해야한다.

1. build.gradle dependencies에 implementation 'com.android.support:multidex:+' 를 추가해준다.

2. build.gradle android의 defalutConfig에 multiDexEnabled true 추가해준다.

3. 매니페스트파일의 <application> 속성으로 android:name="android.support.multidex.MultiDexApplication" 을 추가해준다. 끝!

 

지도에 아이콘 추가하기

오버레이 : 일반적으로 현실 공간을 표현할 땐 레이어로 분리하고 각 레이어에 유사한 속성을 가진 객체들을 넣어준다. 구글맵에선 이 레이어들을 오버레이라 부른다. 지도 전체가 레이어로 구성된것은 아니고 가장 기본적인 정보들은 타일모양 이미지로 만들어 보여주고 경로 표현하는 선이나 내 위치 등을 별도 오버레이로 정의해서 추가할 수 있도록 해준다.

 

내 현재 위치표시를 위한 오버레이 추가하는 방법 : 액티비티가 중지되거나 다시 시작할 때 현재 위치 표시하기 위해 setMyLocationEnabled(true) 를 호출한다. 이 메서드를 onMapReady()안에서 호출하고 액티비티가 화면에 보일때 다시 표시하고 안보일때 없애기 위해 onResume에서 true로 onPause에서 false로 각각호출해준다. 

마커를 사용해서 표시하기 : 

MarkerOptions myLocationMarker; 를 사용해 MarkerOptions를 하나 만들어주고 Location을 보여주는 곳에서

myLocationMarker = new MarkerOptions(); 로 마커 객체 생성해주고 이 마커에 position이나 title, snippet, icon등을 설정해준뒤 map.addMarker(myLocationMarker); 로 지도에 마커를 추가해주면 된다. ㅎㅎㅎ

'안드로이드' 카테고리의 다른 글

푸시 알림 설정하기  (0) 2021.05.10
앱 위젯 만들기  (0) 2021.05.08
위치기반 서비스 이용. 내 위치 알려주기.  (2) 2021.05.06
내용 제공자  (1) 2021.05.04
데이터베이스  (0) 2021.04.29

댓글