이번 포스팅은 Google Map을 활용한 위치기반 서비스 앱 개발이다.
이전 포스팅에서 확인하였듯이 LBS 관련 서비스를 제공하기 위해선 Google Play 서비스 활용이 필수적이다.
[현재의 위치값 가져오기 복습]
Fused Location을 이용해서 위치정보를 받아오는 정보는 아래 3가지 방식을 통해서 받아온다.
- GPS
- 통신사 NW
- Wifi NW
위의 세가지 방식 중 GPS가 가장 정확하지만 배터리 소모가 많고 음영지역이 많다는 단점이 있다. 통신사 NW의 경우 상대적으로 음영지역이 적은 반면에 오차율이 1Km ~ 1.5Km로 너무 넓다는 단점이 있다. Wifi 네트워크를 이용하는 방식은 아직 우리나라에서는 법적으로 제한이 걸려있기 때문에 사용할 수 없다.
Fused Location API를 사용하기 전에 설정을 하면 위의 세가지 방법 중 가장 적절한 방법으로 현재의 위치 값을 가져오게 된다.
[Google Map을 활용]
Web 프로그래밍을할 때 Google Map을 이용하는방법은 정말 간단하다.
<script src=~~>를 통해 Google Map API를 임포트하고 지도를 표시 할 Layout을 설정하고 함수 하나만 콜 하면 될 일이었다.
그렇게 간단하던 Google Map이 안드로이드에서는 상대적으로 엄청 복잡한 과정을 거친다.
Manifest 설정, Fragment를 이용한 화면단 소스코딩 게다가 Android Developer Console에 프로젝트를 등록하여 Authentication Key 값을 생성 및 얻어와야지 비로소 사용할 수 있게된다.
[구현하기]
일단 manifest 파일에 permission 세팅
Google Map 사용을 하기 위해서 키값 입력
Google Map을 표현하기 위해서 Layout.xml에 Fragment를 추가
MainActivity.java
이전 포스팅에서 확인하였듯이 LBS 관련 서비스를 제공하기 위해선 Google Play 서비스 활용이 필수적이다.
[현재의 위치값 가져오기 복습]
Fused Location을 이용해서 위치정보를 받아오는 정보는 아래 3가지 방식을 통해서 받아온다.
- GPS
- 통신사 NW
- Wifi NW
위의 세가지 방식 중 GPS가 가장 정확하지만 배터리 소모가 많고 음영지역이 많다는 단점이 있다. 통신사 NW의 경우 상대적으로 음영지역이 적은 반면에 오차율이 1Km ~ 1.5Km로 너무 넓다는 단점이 있다. Wifi 네트워크를 이용하는 방식은 아직 우리나라에서는 법적으로 제한이 걸려있기 때문에 사용할 수 없다.
Fused Location API를 사용하기 전에 설정을 하면 위의 세가지 방법 중 가장 적절한 방법으로 현재의 위치 값을 가져오게 된다.
[Google Map을 활용]
Web 프로그래밍을할 때 Google Map을 이용하는방법은 정말 간단하다.
<script src=~~>를 통해 Google Map API를 임포트하고 지도를 표시 할 Layout을 설정하고 함수 하나만 콜 하면 될 일이었다.
그렇게 간단하던 Google Map이 안드로이드에서는 상대적으로 엄청 복잡한 과정을 거친다.
Manifest 설정, Fragment를 이용한 화면단 소스코딩 게다가 Android Developer Console에 프로젝트를 등록하여 Authentication Key 값을 생성 및 얻어와야지 비로소 사용할 수 있게된다.
[구현하기]
일단 manifest 파일에 permission 세팅
<permission
android:name="com.example.ch5_lbs.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/> <uses-permission
android:name="com.example.ch5_lbs.permission.MAPS_RECEIVE"/> <uses-permission
android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission
android:name="android.permission.INTERNET"/>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission
android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/> <uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"/>
Google Map 사용을 하기 위해서 키값 입력
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="AIzaSyDQQICJSD3Rx3m6b0AFXiHJOjEeGWM3Sqw"/>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
<activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
Google Map을 표현하기 위해서 Layout.xml에 Fragment를 추가
<fragment
android:id="@+id/map_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:name="com.google.android.gms.maps.SupportMapFragment"/>
MainActivity.java
package com.example.ch5_lbs; import android.location.Location; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.FusedLocationProviderApi; import com.google.android.gms.location.LocationServices; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.UiSettings; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import java.text.DecimalFormat; import java.text.SimpleDateFormat; /** * OnMapReadyCallback: 지도가 준비된 시점을 잡기위한 callback * 이 시점에 map을 이용하지 않으면 시간차의 문제로 nullpoint등의 에러 발생 * */ public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, OnMapReadyCallback { TextView providerTextView; ImageView onOffImageView; TextView timeTextView; TextView locationTextView; TextView accuracyTextView; GoogleApiClient googleApiClient; FusedLocationProviderApi fusedLocationProviderApi; Location currentlocation; GoogleMap map; // fragment에 지도 뿌리는 view @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); providerTextView = (TextView) findViewById(R.id.txt_location_provider); onOffImageView = (ImageView) findViewById(R.id.img_location_on_off); timeTextView = (TextView) findViewById(R.id.gps_time); locationTextView = (TextView) findViewById(R.id.gps_location); accuracyTextView = (TextView) findViewById(R.id.gps_accuracy); /** * Fused API는 실제 google play service라이브러리에서 제공되는 기능으로 * google의 다양한 service를 활용하기 위한 라이브러리이다. * 그중 locationservice쪽을 이용하겠다고 선언 */ googleApiClient = new GoogleApiClient.Builder(this) .addApi(LocationServices.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build(); fusedLocationProviderApi = LocationServices.FusedLocationApi; } private void toast(String msg){ Toast t=Toast.makeText(this, msg, Toast.LENGTH_SHORT); t.show(); } private String getDateTime(long time) { if (time == 0) return ""; SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return formatter.format(new java.util.Date(time)); } private String convertDouble(double input) { DecimalFormat format = new DecimalFormat(".######"); return format.format(input); } /** * 위치정보 획득후 호출 * 매개변수의 정보대로 다양한 정보 추출하고 화면 출력 역할 */ private void updateInfo(Location location){ onOffImageView.setImageResource(R.drawable.on); timeTextView.setText(getDateTime(location.getTime())); locationTextView.setText("LAT:" + convertDouble(location.getLatitude()) +" LNG:" + convertDouble(location.getLongitude())); accuracyTextView.setText(location.getAccuracy() + " meters"); } /** * 위치값 획득후에 호출되어 지도제어 */ private void showMap(Location location){ // 지도에서의 위치는 LatLng로 표현 LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); // 지도 옵션 CameraPosition position = new CameraPosition.Builder().target(latLng).zoom(16f).build(); // 지도의 center 위치 이동 map.moveCamera(CameraUpdateFactory.newCameraPosition(position)); // market 올리기 map.clear(); // 이전 marker지우고 안지우면 중복으로 나옴 map.addMarker(new MarkerOptions().position(latLng).title("Location") .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE))); } @Override protected void onResume() { super.onResume(); googleApiClient.connect(); // 겨리과는 callback함수 호출로 if(map==null){ ((SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map_view)).getMapAsync(this); } } @Override protected void onPause() { super.onPause(); if(googleApiClient.isConnected()){ googleApiClient.disconnect(); } } @Override public void onConnected(@Nullable Bundle bundle) { // 위치값 획득 Location location = fusedLocationProviderApi.getLastLocation(googleApiClient); if(location != null){ currentlocation = location; updateInfo(location); showMap(location); } } @Override public void onConnectionSuspended(int i) { toast("onConnectionSuspended"); } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { toast("onConnectionFailed"); } @Override public void onMapReady(GoogleMap googleMap) { map = googleMap; UiSettings settings = map.getUiSettings(); settings.setZoomControlsEnabled(true); map.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener(){ @Override public void onInfoWindowClick(Marker marker) { toast("info window click..."); } }); } }
댓글 없음:
댓글 쓰기