본문 바로가기

Android/GPS with Google Maps

GPS with Google Maps

GPS위치정보를 MapView와 연결하여 지도상에 현재위치를 표시하는 예

MapView를 이용하여 지도를 출력하기 위해서는 Google Maps API가 필요하므로 Google Maps API Key가 필요하다. API Key를 발급받는 절차는 여기를 참조한다.
GPS를 다루는 기본예제는 여기를 참고한다.
MapView를 이용하여 Google Maps 를 사용하는 예는 여기를 참고한다.
앞의 2가지 예제를 결합하여 현재위치를 지도상에 표현하는 것이 이번 글의 주요 내용이다.
Google Maps API는 외부 라이브러리이며 MapController 클래스를 포함하고 있는데, MapController클래스는 GPS 위치정보를 이용하여 화면의 지도를 이동시킬 수 있는 기능을 갖고 있으므로 여기서는 MapController 의 사용법에 주목해야 한다.

Android 에서 GPS와 Google Maps API를 이용한 간단한 Navigation 프로그램 예


Android Plugin이 설치된 Eclipse에서 Android Project를 생성한다.
이 때 Build Target을 Google APIs 으로 설정하는 것은 Google Maps API를 사용할 때와 동일하다.

AndroidManifest.xml
프로젝트 생성과 함께 기본으로 작성된 내용에 적색의 요소를 추가함

  • com.google.android.maps 는 Google Maps API를 사용하기 위한 것
  • ACCESS_FINE_LOCATION 은 GPS 위치정보에 접근하기 위한 것
  • INTERNET 은 Google 사이트에 접속하여 Google Maps 로부터 지도정보를 받기 위한 것

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.ojtit.android.gps.demo"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
   
     <uses-library android:name="com.google.android.maps" />

         
        <activity android:name=".GPSNavigationActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
    <uses-sdk android:minSdkVersion="7" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />

</manifest>



main.xml
프로젝트와 함께 생성된 내용 중에서 TextView 요소를 MapView요소로 대치한다. Google Maps를 이용하여 지도를 표시하기 위해서는 MapView 를 사용해야 한다.
초록색으로 표시한 Google Maps API Key는 미리 준비되어 있어야 한다. 여기를 참고하세요.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
   
<com.google.android.maps.MapView
    android:id="@+id/mapview1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:enabled="true"
    android:clickable="true"
    android:apiKey="0lbzaFTEjucasdfasdfasdfas-idCXzDE_Ga8XL4Q" />   
   
</LinearLayout>


GPSNavigationActivity.java
GPS 위치정보가 MapController에 의해 새로운 위치로 변경되어 MapView에 나타나 있는 기존 지도를 갱신한다

package com.ojtit.android.gps.demo;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.Toast;

public class GPSNavigationActivity extends MapActivity
{   
    private LocationManager lm;
    private LocationListener locationListener;

    private MapView mapView;
    private MapController mc;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        //---use the LocationManager class to obtain GPS locations---
        lm = (LocationManager)
            getSystemService(Context.LOCATION_SERVICE);   
       
        locationListener = new MyLocationListener();
       
        lm.requestLocationUpdates(
            LocationManager.GPS_PROVIDER,
            0,
            0,
            locationListener);
       
        mapView = (MapView) findViewById(R.id.mapview1);
        mapView.setBuiltInZoomControls(true); //지도 확대/축소기능 활성화

        mc = mapView.getController();

    }

    @Override
    protected boolean isRouteDisplayed() {
        // TODO Auto-generated method stub
        return false;
    }       
   
    private class MyLocationListener implements LocationListener
    {
        @Override
        public void onLocationChanged(Location loc) {
            if (loc != null) {               
                Toast.makeText(getBaseContext(),
                    "Location changed : Lat: " + loc.getLatitude() +
                    " Lng: " + loc.getLongitude(),
                    Toast.LENGTH_SHORT).show();
               
                GeoPoint p = new GeoPoint(
                        (int) (loc.getLatitude() * 1E6), /* 정수로 microdegrees를 표현하기 위함 */
                        (int) (loc.getLongitude() * 1E6));
                mc.animateTo(p);
                mc.setZoom(16);               
                mapView.invalidate();
            }
        }

        @Override
        public void onProviderDisabled(String provider) {
            // TODO Auto-generated method stub
        }

        @Override
        public void onProviderEnabled(String provider) {
            // TODO Auto-generated method stub
        }

        @Override
        public void onStatusChanged(String provider, int status,
            Bundle extras) {
            // TODO Auto-generated method stub
        }
    }   
}


R.java
리소스 설정 내용이 변경되면 시스템에 의해 자동으로 반영되므로 수동으로 편집할 필요가 없으며, main.xml 에서 설정한 MapView의 아이디가 소스코드에서 접근가능하도록 선언되어 있는지만 확인한다.

/* AUTO-GENERATED FILE.  DO NOT MODIFY.
 *
 * This class was automatically generated by the
 * aapt tool from the resource data it found.  It
 * should not be modified by hand.
 */

package com.ojtit.android.gps.demo;

public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
    }
    public static final class id {
        public static final int mapview1=0x7f050000;
    }
    public static final class layout {
        public static final int main=0x7f030000;
    }
    public static final class string {
        public static final int app_name=0x7f040001;
        public static final int hello=0x7f040000;
    }
}


Run As > Android Application 
실행하여 에뮬레이터가 나타나면 DDMS 퍼스펙티브로 전환하여 Location Controls에서 적당한 위도와 경도를 입력하고 'Send' 버튼을 눌러 지도상의 해당 위치가 화면의 중앙에 오는지 확인한다. DDMS 퍼스펙티브 설정은 여기를 참고하세요.
강남구청역 위치 (위도37.51718079924645, 경도127.0412689447403)를 입력하고 'Send' 버튼을 눌러 에뮬레이터로 GPS위치정보를 전달한 결과

사용자 삽입 이미지

사용자 삽입 이미지


사용자 삽입 이미지

배율을 20으로 설정한 경우


아래에 첨부한 위도, 경도를 사용하여 몇번 'Send' 버튼을 눌러보면 해당 위치로 지도가 이동하면서 갱신되는 것을 확인할 수 있다.

참고: Google Map을 이용하여 지리적인 특정위치의 위도, 경도를 확인하는 방법

1. Google Map에서 찾고자 하는 위치에서 마우스 우측을 눌러 [지도 중앙으로 설정]을 선택하면 해당 지점이 지도의 중앙으로 오게 된다.
2. 웹브라우저의 주소창에 다음과 같이 입력하고 엔터를 치면 위도, 경도 정보가 Prompt 입력창에 나타난다.
    javascript:void(prompt('', gApplication.getMap().getCenter()));
3. Prompt 입력창에 나타난 위도, 경도 정보를 복사해서 사용하면 된다.

또 다른 방법
1. http://maps.google.com에 접속하여 상단의 검색란에 지명을 입력하고 [지도검색]을 누른다
2. 검색된 위치에 마우스 우측을 눌러서 '이곳이 궁금한가요?' 항목을 선택한다.
3. 검색란에 입력했던 지명이 사라지고 선택한 곳의 위도/경도가 나타난다.

위의 방법을 사용하면 Android에서 GPS 응용 프로그램을 작성할 때 에뮬레이터에 지리적 위치를 전달하여 실제 지도상의 위치와 정확하게 매핑되는지 확인할 수 있다.

참고: 강남구청역 부근의 위도 및 경도 (위의 방법을 사용함)
(37.51718079924645, 127.0412689447403)
(37.517146760042465, 127.0411616563797)
(37.51707868158788, 127.0411428809166)
(37.51702336779783, 127.0411616563797)
(37.5169829461561, 127.04117774963379)
(37.51695741668687, 127.04109728336334)
(37.516902102806924, 127.04093366861343)
(37.51688721060146, 127.04104632139206)
(37.5169127400947, 127.04119384288788)
(37.516842533967285, 127.04124748706817)
(37.516799984767, 127.04129576683044)
(37.51676594538928, 127.0413064956665)
(37.51665106237492, 127.04134941101074)
(37.516576601067435, 127.04137355089187)
(37.51647661005195, 127.04142183065414)
(37.51638087384775, 127.04145669937134)
(37.516248970431896, 127.04149961471557)
(37.51615536141467, 127.04154253005981)
(37.516006437736195, 127.04159080982208)
(37.51597239799653, 127.04159885644913)
(37.51584049385866, 127.04164981842041)
(37.515710716979356, 127.04170614480972)


sample.gpx
위도와 경도정보만 입력하여 최대한 간단하게 작성함 (위의 좌표를 GPX포맷으로 저장한 것)
DDMS > Location Controls > GPX > Load GPX 버튼을 누르고 이 파일을 찾아서 로드하면 좀더 쉽게 일련의 GPS 위치정보를 에뮬레이터로 전달할 수 있다.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<gpx xmlns="http://www.topografix.com/GPX/1/1"
     version="1.1"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.topografix.com/GPX/gpx_overlay/0/3 http://www.topografix.com/GPX/gpx_overlay/0/3/gpx_overlay.xsd">
<wpt lat="37.51718079924645" lon="127.0412689447403"/>
<wpt lat="37.517146760042465" lon="127.0411616563797"/>
<wpt lat="37.51707868158788" lon="127.0411428809166"/>
<wpt lat="37.51702336779783" lon="127.0411616563797"/>
<wpt lat="37.5169829461561" lon="127.04117774963379"/>
<wpt lat="37.51695741668687" lon="127.04109728336334"/>
<wpt lat="37.516902102806924" lon="127.04093366861343"/>
<wpt lat="37.51688721060146" lon="127.04104632139206"/>
<wpt lat="37.5169127400947" lon="127.04119384288788"/>
<wpt lat="37.516842533967285" lon="127.04124748706817"/>
<wpt lat="37.516799984767" lon="127.04129576683044"/>
<wpt lat="37.51676594538928" lon="127.0413064956665"/>
<wpt lat="37.51665106237492" lon="127.04134941101074"/>
<wpt lat="37.516576601067435" lon="127.04137355089187"/>
<wpt lat="37.51647661005195" lon="127.04142183065414"/>
<wpt lat="37.51638087384775" lon="127.04145669937134"/>
<wpt lat="37.516248970431896" lon="127.04149961471557"/>
<wpt lat="37.51615536141467" lon="127.04154253005981"/>
<wpt lat="37.516006437736195" lon="127.04159080982208"/>
<wpt lat="37.51597239799653" lon="127.04159885644913"/>
<wpt lat="37.51584049385866" lon="127.04164981842041"/>
<wpt lat="37.515710716979356" lon="127.04170614480972"/>
</gpx>


실제폰(Galaxy s)에서 테스트한 화면을 캡쳐함 (강남구청역 부근 OJTIT 강의실에서 )