티스토리 뷰
[Android(안드로이드) 앱 개발 응용] Google Map API로 지도 보여주기(MapView), Overlay Item 그려주기 예제
Unikys 2012. 11. 24. 14:15* 이론공부는 지긋하다! 잠시 외도를 해서 Google Map API를 활용하는 방법을 공부해보자!
2012/11/05 - [Android(안드로이드) 앱 개발 기초] Eclipse 개발환경 설정하기, Android SDK 설치하기
2012/11/07 - [Android(안드로이드) 앱 개발 기초] 안드로이드 프로젝트 생성하고 에뮬레이터로 앱 실행하기
2012/11/10 - [Android(안드로이드) 앱 개발 기초] 간단한 인터페이스 구현과 다른 Activity로 넘어가기
2012/11/21 - [Android(안드로이드) 앱 개발 기초] Activity 라이프사이클 공부
* Google Map API 설치하기
: Google Map API는 Google API에 포함되어 있으며, Android SDK를 설치하면 Google API도 SDK Manager를 통해서 쉽게 설치할 수 있다. SDK Manager를 열어서 Google API를 클릭하고 인스톨하면 된다.
: Google API를 클릭하여 인스톨하고나면 Android Virtual Device(AVD) Manager에서 에뮬레이터가 Android SDK가 아니라 Google API를 이용하도록 설정해야한다. 따라서 AVD Manager로 가서 New... 버튼을 누르면 아래와 같은 창이 뜨고, Target > Google APIs (Google Inc.)을 선택하도록 한다. (자신이 개발하는 Android SDK와 맞는 버전의 API Level을 선택하도록 한다.) 그리고 Create AVD 버튼을 클릭하면 새로운 에뮬레이터가 생성된다.
: 아래와 같이 AVD Manager에 새로운 에뮬레이터가 추가된 것을 확인할 수 있다.
: 그리고 이제 실행 대상을 정해야하는데, Run as > Run Configuration으로 가서 Name 바로 아래에 있는 Target으로 가서 새로 만든 AVD를 선택하고 Apply를 하면 AVD까지 설정은 끝난 것이다.
* Map Activity 생성하기
: 프로젝트를 만들고 시작할 때 Google API를 사용하도록 설정해주면서 시작하자.
: Activity로 MyMapActivity 등으로 명명해서 생성하자.
: 그다음 AndroidManifest.xml에서 맵을 이용한다는 것을 명시해뭐야한다. AndroidManifest.xml을 열어서 아래의 태그를 <application> 태그 안에 추가해주자.
<uses-library android:name="com.google.android.maps"/>
: 그리고 인터넷 접속이 필요하므로 인터넷 접속을 허용시키자. 아래의 태그를 <manifest> 태그 안에 넣자.
<uses-permission android:name="android.permission.INTERNET"/>
: 만약 지도가 더 넓은 영역을 차지하기를 원한다면 activity의 android:theme를 titlebar가 없도록 설정하면 된다.
<activity android:name=".MyMapActivity" android:label="@string/title_activity_map" android:theme="@android:style/Theme.NoTitleBar">
: 예로 아래와 같이 AndroidManifest.xml 파일 안에 넣으면 된다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="unikys.icu" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="15" /> <uses-permission android:name="android.permission.INTERNET"/> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MyMapActivity" android:label="@string/title_activity_map" android:theme="@android:style/Theme.NoTitleBar"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <uses-library android:name="com.google.android.maps"/> </application> </manifest>
: 그리고 UI에 MapView를 추가해주자. res/layout/activity_mymap.xml 파일을 열어서 MapView를 추가해주자.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <com.google.android.maps.MapView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/mapview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:apiKey="키를 발급받아 여기 입력" /> </RelativeLayout>
: 위의 android:apiKey는 Google Map API Key를 받아서 입력을 해야한다. 이것은 개발할 때에도 반드시 입력해야하는 사항이므로 Google Map API Key를 신청해보자.
* Google Map API Key 신청하기
: 구글 디버깅에는 자체 keystore가 있지만, Google Map API구글 맵 API 키를 신청하기 위해서는 MD5 fingerprint가 필요하다. 여기서 중요한 것이 바로 API key가 debug용이 있고 release용이 있다는 것이다. 개발을 할 때에는 debug용을 사용해야 에뮬레이터 등에서 나오고 release용을 사용해야 나중에 스토어에 올렸을 때 제대로 나올 것이다. 개발용이라면 1-b로 가서 개발용으로 등록해서 사용하고 스토어에 올리는 것이라면 1-a에서 keystore를 생성해서 MD5를 등록하면 된다.
1-a keystore 생성해서 MD5 fingerprint 받아오기
: 나중에 스토어에 올리려면 기본적으로 필요한 작업이므로 미리 해두는 것도 좋을 것이다. 일단 keytool을 이용해서 keystore 파일을 생성하는 방법은 아래와 같다. keytool 은 jdk에서 제공을 해주고 있으며, JAVA_HOME이 환경에 추가되었다면 어디에서든 설정 가능할 것이다. 다음과 같이 실행해서 .keystore 파일을 생성하자.
$ keytool -genkey -v -keystore {my-release-key.keystore} -alias {alias_name} -keyalg RSA -keysize 2048 -validity 10000
: 위의 파라미터 설명은 다음과 같다.
파라미터 |
설명 |
-genkey |
public - private 키 페어를 생성 |
-v | verbose 아웃풋 설정 |
-keystore <keystore-name>.keystore |
private key를 저장하고 있을 keystore |
-alias <alias_name> |
생성하는 키에 대한 alias 설정, 첫 8자까지만 사용된다. |
-keyalg <alg> |
암호화 알고리즘 설정, alg = {DSA | RSA} |
-keysize <size> |
생성할 키의 bit 크기, 기본값은 1024이나 2048이나 그 이상을 추천 |
-validity <valdays> | 생성한 키가 유효한 날수, 10000이나 그 이상 추천 |
: keystore의 이름과 alias 이름을 정해준 다음에 실행을 하면 암호를 물어보고, 개인 정보들을 물어볼 것이다. 순서대로 입력하고 마지막 correct? 물어보는 질문에서 y를 입력하면 keystore를 생성해준다.
MacBook-Pro:Desktop unikys$ keytool -genkey -v -keystore my-release-key.keystore -alias unikys -keyalg RSA -keysize 2048 -validity 10000 Enter keystore password: Re-enter new password: What is your first and last name? [Unknown]: unikys What is the name of your organizational unit? [Unknown]: tistory What is the name of your organization? [Unknown]: tistory What is the name of your City or Locality? [Unknown]: Seoul What is the name of your State or Province? [Unknown]: Seoul What is the two-letter country code for this unit? [Unknown]: kr Is CN=unikys, OU=tistory, O=tistory, L=Seoul, ST=Seoul, C=kr correct? [no]: y Generating 2,048 bit RSA key pair and self-signed certificate (SHA1withRSA) with a validity of 10,000 days for: CN=unikys, OU=tistory, O=tistory, L=Seoul, ST=Seoul, C=kr Enter key password for(RETURN if same as keystore password): Re-enter new password: [Storing my-release-key.keystore]
: 이런 단계들을 거치고나면 my-release-key.keystore가 생긴 것을 확인할 수 있을 것이다. 그럼 다시 keytool을 실행해서 해당하는 keystore의 MD5 fingerprint를 알아내자. 이전에 입력했던 -alias와 -keystore의 이름을 똑같이 입력하고 비밀번호를 입력하면 MD5 값을 돌려준다.
MacBook-Pro:Desktop unikys$ keytool -list -alias unikys -keystore my-release-key.keystore Enter keystore password: unikys, Nov 24, 2012, PrivateKeyEntry, Certificate fingerprint (MD5): 42:0A:25:01:32:24:B8:61:1B:E4:82:66:2A:4E:A1:71
1-b 개발용 keystore에서 MD5 fingerprint 찾기
: 기본 debug keystore를 통해서도 MD5를 생성해서 사용할수가 있는데, debug keystore는 아래와 같다.
- Windows Vista: C:\Users\
\.android\debug.keystore Windows XP: C:\Documents and Settings\ \.android\debug.keystore OS X and Linux: ~/.android/debug.keystore
: 그래서 위의 MD5를 keytool을 실행하면 되는데, -keystore의 keystore 파일 값에 위의 운영체제별 keystore 위치를 넣고 패스워드를 기본으로 입력하면 MD5가 출력된다.
MacBook-Pro:Desktop unikys$ keytool -list -alias androiddebugkey -keystore ~/.android/debug.keystore -storepass android -keypass android androiddebugkey, Feb 10, 2012, PrivateKeyEntry, Certificate fingerprint (MD5): 51:05:A6:48:B2:3D:A2:4F:C1:13:37:52:BC:15:F3:2B
2. keystore의 MD5 fingerprint를 이용해서 등록하기
: 아래의 사이트에 들어가서 약관을 읽어보고 동의를 한 다음, MD5를 이용해서 등록하자.
http://code.google.com/android/maps-api-signup.html
: 신청을 하게 되면 구글 계정으로 로그인을 하게 되고 그 이후에 그럼 아래와 같이 API key가 생성이 되고, 해당하는 keystore로 등록된 앱들에 대해서는 모두 동일하게 사용이 가능하다는 것과 xml layout의 예까지 보여준다.
: 위의 예가 나온대로 다시 res/layout/activity_mymap.xml로 가서 apiKey를 입력하자.
* Google Map API 사용하기
: API key를 입력했다면 MyMapActivity.java로 가서 기본 Activity에서 MapActivity로 바꿔주자.
import com.google.android.maps.MapActivity; public class ICUMapActivity extends MapActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_icumap); MapView mapView = (MapView) findViewById(R.id.mapview); mapView.setBuiltInZoomControls(true); } @Override protected boolean isRouteDisplayed() { return false; } //... 생략
: 위의 MapActivity는 isRouteDisplay 함수를 구현해야하므로 추가하고, Activity가 생성될 때 MapView도 초기화해주자. 이제 처음에 만들었던 Google API를 사용하는 에뮬레이터로 실행하자.
: 잘된다! 무수한 에러들이 나는 것은 나중에 정식 등록해서 스토어에 올리게 되면 해결되므로 일단 무시해도 되고, 만약 에뮬레이터 상에서 지도가 안뜨면서 아래와 같은 에러가 난다면,
11-24 13:23:44.128: W/System.err(674): IOException processing: 26
11-24 13:23:44.128: W/System.err(674): java.io.IOException: Server returned: 3
: 위의 "1-b 개발용 keystore에서 MD5 fingerprint 찾기"를 보고 천천히 다시 해보면 될 것이다.
* 주의: 만약에 스토어에 올린다면 개발용에서 signed up keystore를 이용해서 새로 API key를 발급받아서 사용하자!
* 맵 위에 오브젝트 그리기
: 맵위에 덮어지는 오브젝트를 그리려면 ItemizedOverlay 클래스를 확장하는 클래스를 만들어야한다. ItemizedOverlay 클래스는 지도 위에 그려지는 모든 Overlay 아이템들을 관리하는 클래스이다.
1. MyItemizedOverlay 클래스를 새로 만들고, ItemizedOverlay 클래스를 extend하도록 한다.
: New > Class > Name에 클래스 이름 입력 > superclass에 Browse 버튼 클릭 > Itemized... 검색하고 OK
: Superclass에서 정상적으로 선택된 것을 확인하고 ItemizedOverlay<Item>의 템플릿으로 있는 것을 ItemizedOverlay<OverlayItem>로 수정하고 Finish 버튼
* MyItemizedOverlay 구현하기
: 일단 OverlayItem 들을 저장할 ArrayList를 저장하자.
private ArrayListmOverlays = new ArrayList ();
: 그리고 ItemizedOverlay의 생성자를 구현재주자. 생성자에서 넘어오는 Drawable을 제대로 표시해주기 위해서는 bound를 제대로 설정해줘야한다. 아래의 중심을 기준으로 삼고자 한다면 boundCenterBottom() 함수를 이용하면 된다. 즉, 좌표지점을 설정했을 때 이미지의 어느 부분이 오는가 설정하는 것이다.
public HelloItemizedOverlay(Drawable defaultMarker) { super(boundCenterBottom(defaultMarker)); }
: OverlayItem을 추가해주고 싶다면 다음의 함수를 구현하면 된다. OverlayItem을 저장하고 있는 ArrayList에 추가할 아이템을 저장하고, ItemizedOverlay의 함수인 populate() 함수를 실행하게 된다.
public void addOverlay(OverlayItem overlay) { mOverlays.add(overlay); populate(); }
: 그리고 만약 populate() 함수가 호출하게 된다면 ItemizedOverlay 안에 있는 createItem(int) 함수가 호출 될 것이고, 또한 OverlayItem의 수를 물어보는 size() 함수 또한 구현해야한다.
@Override protected OverlayItem createItem(int index) { return this.mOverlays.get(index); } @Override public int size() { return this.mOverlays.size(); }
: 이제 OverlayItem의 터치 이벤트를 감지하는 것을 해보자. 먼저 앱의 Context의 정보를 이용해야하므로 멤버 변수로 mContext를 추가해주고 생성자에 앱의 Context를 추가로 받을 수 있도록 해주자.
private Context mContext; public ICUItemizedOverlay(Drawable defaultMarker, Context context) { super(boundCenterBottom(defaultMarker)); this.mContext = context; }
: 그리고 ItemizedOverlay 함수의 onTap(int index) 함수를 override해서 멤버변수로 저장한 Context를 이용해서 알림을 띄우자.
@Override protected boolean onTap(int index) { OverlayItem item = mOverlays.get(index); AlertDialog.Builder dialog = new AlertDialog.Builder(mContext); dialog.setTitle(item.getTitle()); dialog.setMessage(item.getSnippet()); dialog.show(); return true; }
: 여기까지 했으면 이제 MyItemizedOverlay 클래스를 이용해서 OverlayItem들을 배치할 수 있게 된 것이다. 다음에는 아래와 같이 마커로 사용할 이미지를 res/drawable/ 폴더 안에 넣어주면 R.java 파일 안에 R.drawable안에 해당하는 파일 명으로 변수가 자동으로 생성된다. (해상도에 따라 hdpi, mdpi 등 안에 다른 마커를 넣어주면 좋다.)
: 이제 다시 MyMapActivity로 가서, onCreate로 가서 MyItemizedOverlay를 설정하는 코드를 추가하자.
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_mymap); MapView mapView = (MapView) findViewById(R.id.mapview); mapView.setBuiltInZoomControls(true); List
mapOverlays = mapView.getOverlays(); Drawable drawable = this.getResources().getDrawable(R.drawable.androidmarker); MyItemizedOverlay itemizedoverlay = new MyItemizedOverlay(drawable, this); GeoPoint point = new GeoPoint(19240000,-99120000); OverlayItem overlayitem = new OverlayItem(point, "Hola, Mundo!", "I'm in Mexico City!"); itemizedoverlay.addOverlay(overlayitem); mapOverlays.add(itemizedoverlay); }
: 위의 소스 코드에서 mapView의 모든 Overlay들의 목록은 mapView 객체에 있는 list를 가져와서 추가를 해야하므로 일단 mapView.getOverlays()로 몸ㄱ록을 가져오고, drawable에 등록한 이미지로 Drawable로 마커를 생성한 다음에, 아까 구현한 MyItemizedOverlay에 생성한 마커와 함께 Context인 this를 넘겨줘서 초기화를 해준다. 그 다음에 마커를 찍을 포인트인 GeoPoint로 생성하고, OverlayItem을 하나 새롭게 만들어서 구현한 MyItemizedOverlay 클래스에 넘겨주고 이 MyItemizedOverlay 클래스는 다시 MapView로 넘겨주면 된다.
: 위의 소스를 실행해서 테스트해보자.
: 위의 좌표대로 위치가 찍혔다! 그리고 마커를 클릭하면 위에서 onTap으로 구현했던 함수가 호출이 된다!
: 잘 작동된다! 이제 나중에 스토어에 올릴때 API key를 바꾸는 것만 잊지 않으면 된다! (하지만 까먹을듯..ㅠ)
- 다음에는 또 다른 응용으로 GPS센서로 좌표 받아오는 것과 지도에 표시해보는 것을 해보자.
* 안드로이드로 Google Map 이용하기 끝.
- 다음 글
2012/11/28 - [Android(안드로이드) 앱 개발 응용] Location GPS 위치 가져오기 및 최적화
2012/12/05 - [Android(안드로이드) 앱 개발 기초] 런타임 설정(로테이션, orientation) 변환 라이프사이클
2012/12/19 - [Android(안드로이드) 앱 개발 응용] 쉽게 Google Map 위에 말풍선 띄우기
2013/03/03 - [Android(안드로이드) 앱 개발 기초] Fragment 기초
2014/09/24 - [Android(안드로이드) 앱 개발 기초] ContentProvider 앱 간 데이터 공유 기본
2014/10/20 - [Android(안드로이드) 앱 개발 기초] MediaPlayer 음악 재생하기
- Total
- Today
- Yesterday
- gae
- ny-school
- K100D
- 뽐뿌
- GX-10
- 샷
- 자바스크립트
- 팁
- Python
- 속깊은 자바스크립트 강좌
- java
- 안드로이드 앱 개발 기초
- php
- 서울
- Android
- 사진
- gre
- Writing
- 탐론 17-50
- c++
- google app engine
- 안드로이드
- HTML5
- Javascript
- TIP
- HTML5 튜토리얼
- 삼식이
- mini project
- lecture
- 강좌
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |