GoogleApiClient와 FusedLocationApi를 사용하여 구글맵에 현재 위치를 표시하는 예제입니다.




최종 업데이트 - 2017. 8. 17


실시간 현재 위치로 지도 이동과 카메라 줌 관련 문제 수정하며 전체적으로 로직을 수정했습니다.

테스트 중 문제 발생시 알려주세요.




1. 구현된 내용

2. 실행 과정 설명

3. 프로그램 흐름

4. 소스 코드

5. 관련 포스팅

   5.1. Google Maps Android API 사용 방법 및 예제

   5.2. Places API Web Service를 사용하여 Android Google Map에 현재 위치 주변의 음식점 표시하기

   5.3. GenyMotion 가상머신에 Google Apps설치하여 Google Maps Android API 태스트 하기





1. 구현된 내용


현재 구현된 내용은 다음과 같습니다.


  • 현재 위치를 지도 상에 마커로 표시해줍니다.

  • 디바이스의 위치 서비스(GPS)가 비활성화 되어 있는 경우 사용자가 활성화하도록 요구합니다.

  • 디바이스의 운영체제 버전이 안드로이드 6.0일 경우에는 위치 관련 퍼미션을 런타임에 요구합니다.

  • 카메라 줌(zoom)을 onMapReady() 메소드에만 지정해주기 때문에 이후에는 사용자가 원하는 줌으로 지도를 볼 수 있습니다.

  • 현재 위치가 변경되면 계속 카메라가 이동하여 현재 위치를 중심으로 지도를 보여주게 됩니다.

  • 사용자가 지도상의 위치를 이동하면  현재 위치 버튼을 누르기 전까지 현재 위치 중심으로 지도 이동이 중단됩니다.  




2. 실행 과정 설명


처음 실행하면 지도의 초기위치를 서울로 이동시키고 위치 정보 사용을 위한 퍼미션 허가를 사용자에게 요청합니다.  

Android 6.0 미만 운영체제를 사용하는 안드로이드 디바이스에서는 보이지 않습니다.




처음 실행하면 안드로이드 디바이스가 현재 위치를 찾는데 시간이 걸립니다.

적절한 조치를 안해주면 아프리카 대륙 옆에 있는 바다가 보입니다.



여러가지 방법이 있지만 저는 서울로 초기위치를 이동시켜주는 방법을 사용했습니다.

onMapReady() 메소드에서 서울로 카메라를 이동시켜줍니다.

그래서 앱에서 GPS가 사용 못하더라도 서울을 보여주게 됩니다.


다른 방법은 마지막에 안드로이드폰이 위치를 인식했던 정보를 가져오는 방법이 있습니다.

아래 링크를 참고하세요..

https://developer.android.com/training/location/retrieve-current.html




위치 서비스가 비활성화되어 있는 경우 활성화 여부를 사용자에게 물어봅니다.





설정을 선택했다면, 위치 정보 설정이 보입니다.

활성화시키고 백버튼을 눌러 앱으로 돌아오면  





현재 위치에 코드에서 추가한 파란색 마커와 구글맵에서 현재 위치를 표시하는데 사용되는 파란색 동그라미가 표시됩니다.





마커를 터치하면 현재 위치의 주소와 좌표가 표시됩니다.





안드로이드 디바이스를 움직이면 현재 위치가 달라짐에 따라 파란색 마커의 위치가 이동하게 됩니다.




3. 프로그램 흐름


앱을 실행시키면 다음 순서대로 메소드들이 실행됩니다.

(런타임 퍼미션, GPS 활성화를 제외한 상태입니다.)


D/googlemap_example: onCreate

D/googlemap_example: onStart: mGoogleApiClient connect

D/googlemap_example: onMapReady :

D/googlemap_example: onConnected : 퍼미션 가지고 있음

D/googlemap_example: onConnected : call startLocationUpdates

D/googlemap_example: startLocationUpdates : call FusedLocationApi.requestLocationUpdates




이제 일정시간마다 현재 위치를 업데이트합니다.


D/googlemap_example: onLocationChanged :

D/googlemap_example: setCurrentLocation :  mGoogleMap moveCamera 37.7110829 126.906244

D/googlemap_example: onLocationChanged :

D/googlemap_example: setCurrentLocation :  mGoogleMap moveCamera 37.7110829 126.906244

D/googlemap_example: onLocationChanged :

D/googlemap_example: setCurrentLocation :  mGoogleMap moveCamera 37.7110829 126.906244

D/googlemap_example: onLocationChanged :

D/googlemap_example: setCurrentLocation :  mGoogleMap moveCamera 37.7110829 126.906244




백버튼을 눌러서 앱종료시 다음 순서대로 메소드가 실행됩니다.


D/googlemap_example: onStop : call stopLocationUpdates

D/googlemap_example: stopLocationUpdates : call FusedLocationApi.removeLocationUpdates

D/googlemap_example: onStop : mGoogleApiClient disconnect




4. 소스 코드


다음 포스팅을 기반으로 수정합니다.  중복되는 내용은 빠져있습니다.


Google Maps Android API 사용 방법 및 예제

http://webnautes.tistory.com/647




1. 매네페스트 파일 AndroidManifest.xml<manifest> 태그 하위요소로 <uses-permission> 태그를 사용하여 위치정보 접근을 위한 퍼미션을 추가해줍니다.


<manifest xmlns:android="http://schemas.android.com/apk/res/android"

   package="com.tistory.webnautes.googlemapsandroidapiexample">


   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

   

   <application

       android:allowBackup="true"

       android:icon="@mipmap/ic_launcher"

       android:label="@string/app_name"

       android:roundIcon="@mipmap/ic_launcher_round"

       android:supportsRtl="true"

       android:theme="@style/AppTheme">



   

2.  MainActivity.java에 다음 코드를 추가합니다.


package com.tistory.webnautes.googlemapsandroidapiexample;


import android.Manifest;

import android.annotation.TargetApi;

import android.content.DialogInterface;

import android.content.Intent;

import android.content.pm.PackageManager;

import android.location.Address;

import android.location.Geocoder;

import android.location.Location;

import android.location.LocationManager;

import android.net.Uri;

import android.os.Build;

import android.provider.Settings;

import android.support.annotation.NonNull;

import android.support.v4.app.ActivityCompat;

import android.support.v4.content.ContextCompat;

import android.support.v7.app.AlertDialog;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.util.Log;

import android.view.WindowManager;

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.LocationListener;

import com.google.android.gms.location.LocationRequest;

import com.google.android.gms.location.LocationServices;

import com.google.android.gms.maps.CameraUpdate;

import com.google.android.gms.maps.CameraUpdateFactory;

import com.google.android.gms.maps.GoogleMap;

import com.google.android.gms.maps.MapFragment;

import com.google.android.gms.maps.OnMapReadyCallback;

import com.google.android.gms.maps.model.BitmapDescriptorFactory;

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.io.IOException;

import java.util.List;

import java.util.Locale;



public class MainActivity extends AppCompatActivity

       implements OnMapReadyCallback,

       GoogleApiClient.ConnectionCallbacks,

       GoogleApiClient.OnConnectionFailedListener,

       LocationListener{



   private GoogleApiClient mGoogleApiClient = null;

   private GoogleMap mGoogleMap = null;

   private Marker currentMarker = null;


   private static final String TAG = "googlemap_example";

   private static final int GPS_ENABLE_REQUEST_CODE = 2001;

   private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 2002;

   private static final int UPDATE_INTERVAL_MS = 1000;  // 1초

   private static final int FASTEST_UPDATE_INTERVAL_MS = 500; // 0.5초


   private AppCompatActivity mActivity;

   boolean askPermissionOnceAgain = false;

   boolean mRequestingLocationUpdates = false;

   Location mCurrentLocatiion;

   boolean mMoveMapByUser = true;

   boolean mMoveMapByAPI = true;


   LocationRequest locationRequest = new LocationRequest()

           .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)

           .setInterval(UPDATE_INTERVAL_MS)

           .setFastestInterval(FASTEST_UPDATE_INTERVAL_MS);



   @Override

   protected void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);


       getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,

               WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

       setContentView(R.layout.activity_main);


       Log.d(TAG, "onCreate");

       mActivity = this;



       mGoogleApiClient = new GoogleApiClient.Builder(this)

               .addConnectionCallbacks(this)

               .addOnConnectionFailedListener(this)

               .addApi(LocationServices.API)

               .build();



       MapFragment mapFragment = (MapFragment) getFragmentManager()

               .findFragmentById(R.id.map);

       mapFragment.getMapAsync(this);

   }



   @Override

   public void onResume() {


       super.onResume();


       if (mGoogleApiClient.isConnected()) {


           Log.d(TAG, "onResume : call startLocationUpdates");

           if (!mRequestingLocationUpdates) startLocationUpdates();

       }



       //앱 정보에서 퍼미션을 허가했는지를 다시 검사해봐야 한다.

       if (askPermissionOnceAgain) {


           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

               askPermissionOnceAgain = false;


               checkPermissions();

           }

       }

   }



   private void startLocationUpdates() {


       if (!checkLocationServicesStatus()) {


           Log.d(TAG, "startLocationUpdates : call showDialogForLocationServiceSetting");

           showDialogForLocationServiceSetting();

       }else {


           if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED

                   && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {


               Log.d(TAG, "startLocationUpdates : 퍼미션 안가지고 있음");

               return;

           }



           Log.d(TAG, "startLocationUpdates : call FusedLocationApi.requestLocationUpdates");

           LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this);

           mRequestingLocationUpdates = true;

       }


   }




   private void stopLocationUpdates() {


       Log.d(TAG,"stopLocationUpdates : LocationServices.FusedLocationApi.removeLocationUpdates");

       LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);

       mRequestingLocationUpdates = false;

   }




   @Override

   public void onMapReady(GoogleMap googleMap) {


       Log.d(TAG, "onMapReady :");


       mGoogleMap = googleMap;



       //런타임 퍼미션 요청 대화상자나 GPS 활성 요청 대화상자 보이기전에

       //지도의 초기위치를 서울로 이동

       setDefaultLocation();


       //mGoogleMap.getUiSettings().setZoomControlsEnabled(false);

       mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);

       mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(15));

       mGoogleMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener(){


           @Override

           public boolean onMyLocationButtonClick() {


               Log.d( TAG, "onMyLocationButtonClick : 위치에 따른 카메라 이동 활성화");

               mMoveMapByAPI = true;

               return true;

           }

       });

       mGoogleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {


           @Override

           public void onMapClick(LatLng latLng) {


               Log.d( TAG, "onMapClick :");

           }

       });


       mGoogleMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {


           @Override

           public void onCameraMoveStarted(int i) {


               if (mMoveMapByUser == true && mRequestingLocationUpdates){


                   Log.d(TAG, "onCameraMove : 위치에 따른 카메라 이동 비활성화");

                   mMoveMapByAPI = false;

               }


               mMoveMapByUser = true;


           }

       });



       mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {


           @Override

           public void onCameraMove() {



           }

       });

   }



   @Override

   public void onLocationChanged(Location location) {



       Log.d(TAG, "onLocationChanged : ");


       String markerTitle = getCurrentAddress(location);

       String markerSnippet = "위도:" + String.valueOf(location.getLatitude())

               + " 경도:" + String.valueOf(location.getLongitude());


       //현재 위치에 마커 생성하고 이동

       setCurrentLocation(location, markerTitle, markerSnippet);


       mCurrentLocatiion = location;

   }



   @Override

   protected void onStart() {


       if(mGoogleApiClient != null && mGoogleApiClient.isConnected() == false){


           Log.d(TAG, "onStart: mGoogleApiClient connect");

           mGoogleApiClient.connect();

       }


       super.onStart();

   }


   @Override

   protected void onStop() {


       if (mRequestingLocationUpdates) {


           Log.d(TAG, "onStop : call stopLocationUpdates");

           stopLocationUpdates();

       }


       if ( mGoogleApiClient.isConnected()) {


           Log.d(TAG, "onStop : mGoogleApiClient disconnect");

           mGoogleApiClient.disconnect();

       }


       super.onStop();

   }



   @Override

   public void onConnected(Bundle connectionHint) {



       if ( mRequestingLocationUpdates == false ) {


           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {


               int hasFineLocationPermission = ContextCompat.checkSelfPermission(this,

                       Manifest.permission.ACCESS_FINE_LOCATION);


               if (hasFineLocationPermission == PackageManager.PERMISSION_DENIED) {


                   ActivityCompat.requestPermissions(mActivity,

                           new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},

                           PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);


               } else {


                   Log.d(TAG, "onConnected : 퍼미션 가지고 있음");

                   Log.d(TAG, "onConnected : call startLocationUpdates");

                   startLocationUpdates();

                   mGoogleMap.setMyLocationEnabled(true);

               }


           }else{


               Log.d(TAG, "onConnected : call startLocationUpdates");

               startLocationUpdates();

               mGoogleMap.setMyLocationEnabled(true);

           }

       }

   }



   @Override

   public void onConnectionFailed(ConnectionResult connectionResult) {


       Log.d(TAG, "onConnectionFailed");

       setDefaultLocation();

   }



   @Override

   public void onConnectionSuspended(int cause) {


       Log.d(TAG, "onConnectionSuspended");

       if (cause == CAUSE_NETWORK_LOST)

           Log.e(TAG, "onConnectionSuspended(): Google Play services " +

                   "connection lost.  Cause: network lost.");

       else if (cause == CAUSE_SERVICE_DISCONNECTED)

           Log.e(TAG, "onConnectionSuspended():  Google Play services " +

                   "connection lost.  Cause: service disconnected");

   }



   public String getCurrentAddress(Location location) {


       //지오코더... GPS를 주소로 변환

       Geocoder geocoder = new Geocoder(this, Locale.getDefault());


       List<Address> addresses;


       try {


           addresses = geocoder.getFromLocation(

                   location.getLatitude(),

                   location.getLongitude(),

                   1);

       } catch (IOException ioException) {

           //네트워크 문제

           Toast.makeText(this, "지오코더 서비스 사용불가", Toast.LENGTH_LONG).show();

           return "지오코더 서비스 사용불가";

       } catch (IllegalArgumentException illegalArgumentException) {

           Toast.makeText(this, "잘못된 GPS 좌표", Toast.LENGTH_LONG).show();

           return "잘못된 GPS 좌표";


       }



       if (addresses == null || addresses.size() == 0) {

           Toast.makeText(this, "주소 미발견", Toast.LENGTH_LONG).show();

           return "주소 미발견";


       } else {

           Address address = addresses.get(0);

           return address.getAddressLine(0).toString();

       }


   }



   public boolean checkLocationServicesStatus() {

       LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);


       return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)

               || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

   }



   public void setCurrentLocation(Location location, String markerTitle, String markerSnippet) {


       mMoveMapByUser = false;



       if (currentMarker != null) currentMarker.remove();



       LatLng currentLatLng = new LatLng(location.getLatitude(), location.getLongitude());


       //구글맵의 디폴트 현재 위치는 파란색 동그라미로 표시

       //마커를 원하는 이미지로 변경하여 현재 위치 표시하도록 수정해야함.

       MarkerOptions markerOptions = new MarkerOptions();

       markerOptions.position(currentLatLng);

       markerOptions.title(markerTitle);

       markerOptions.snippet(markerSnippet);

       markerOptions.draggable(true);

       markerOptions.icon(BitmapDescriptorFactory

               .defaultMarker(BitmapDescriptorFactory.HUE_BLUE));

       currentMarker = mGoogleMap.addMarker(markerOptions);



       if ( mMoveMapByAPI ) {


           Log.d( TAG, "setCurrentLocation :  mGoogleMap moveCamera "

                   + location.getLatitude() + " " + location.getLongitude() ) ;

          // CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(currentLatLng, 15);

           CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(currentLatLng);

           mGoogleMap.moveCamera(cameraUpdate);

       }

   }



   public void setDefaultLocation() {


       mMoveMapByUser = false;



       //디폴트 위치, Seoul

       LatLng DEFAULT_LOCATION = new LatLng(37.56, 126.97);

       String markerTitle = "위치정보 가져올 수 없음";

       String markerSnippet = "위치 퍼미션과 GPS 활성 요부 확인하세요";



       if (currentMarker != null) currentMarker.remove();


       MarkerOptions markerOptions = new MarkerOptions();

       markerOptions.position(DEFAULT_LOCATION);

       markerOptions.title(markerTitle);

       markerOptions.snippet(markerSnippet);

       markerOptions.draggable(true);

       markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));

       currentMarker = mGoogleMap.addMarker(markerOptions);


       CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(DEFAULT_LOCATION, 15);

       mGoogleMap.moveCamera(cameraUpdate);


   }



   //여기부터는 런타임 퍼미션 처리을 위한 메소드들

   @TargetApi(Build.VERSION_CODES.M)

   private void checkPermissions() {

       boolean fineLocationRationale = ActivityCompat

               .shouldShowRequestPermissionRationale(this,

                       Manifest.permission.ACCESS_FINE_LOCATION);

       int hasFineLocationPermission = ContextCompat.checkSelfPermission(this,

               Manifest.permission.ACCESS_FINE_LOCATION);


       if (hasFineLocationPermission == PackageManager

               .PERMISSION_DENIED && fineLocationRationale)

           showDialogForPermission("앱을 실행하려면 퍼미션을 허가하셔야합니다.");


       else if (hasFineLocationPermission

               == PackageManager.PERMISSION_DENIED && !fineLocationRationale) {

           showDialogForPermissionSetting("퍼미션 거부 + Don't ask again(다시 묻지 않음) " +

                   "체크 박스를 설정한 경우로 설정에서 퍼미션 허가해야합니다.");

       } else if (hasFineLocationPermission == PackageManager.PERMISSION_GRANTED) {



           Log.d(TAG, "checkPermissions : 퍼미션 가지고 있음");



           if ( mGoogleApiClient.isConnected() == false) {


               Log.d(TAG, "checkPermissions : 퍼미션 가지고 있음");

               mGoogleApiClient.connect();

           }

       }

   }


   @Override

   public void onRequestPermissionsResult(int permsRequestCode,

                                          @NonNull String[] permissions,

                                          @NonNull int[] grantResults) {


       if (permsRequestCode

               == PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION && grantResults.length > 0) {


           boolean permissionAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;


           if (permissionAccepted) {



               if ( mGoogleApiClient.isConnected() == false) {


                   Log.d(TAG, "onRequestPermissionsResult : mGoogleApiClient connect");

                   mGoogleApiClient.connect();

               }




           } else {


               checkPermissions();

           }

       }

   }



   @TargetApi(Build.VERSION_CODES.M)

   private void showDialogForPermission(String msg) {


       AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

       builder.setTitle("알림");

       builder.setMessage(msg);

       builder.setCancelable(false);

       builder.setPositiveButton("예", new DialogInterface.OnClickListener() {

           public void onClick(DialogInterface dialog, int id) {

               ActivityCompat.requestPermissions(mActivity,

                       new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},

                       PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);

           }

       });


       builder.setNegativeButton("아니오", new DialogInterface.OnClickListener() {

           public void onClick(DialogInterface dialog, int id) {

               finish();

           }

       });

       builder.create().show();

   }


   private void showDialogForPermissionSetting(String msg) {


       AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

       builder.setTitle("알림");

       builder.setMessage(msg);

       builder.setCancelable(true);

       builder.setPositiveButton("예", new DialogInterface.OnClickListener() {

           public void onClick(DialogInterface dialog, int id) {


               askPermissionOnceAgain = true;


               Intent myAppSettings = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,

                       Uri.parse("package:" + mActivity.getPackageName()));

               myAppSettings.addCategory(Intent.CATEGORY_DEFAULT);

               myAppSettings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

               mActivity.startActivity(myAppSettings);

           }

       });

       builder.setNegativeButton("아니오", new DialogInterface.OnClickListener() {

           public void onClick(DialogInterface dialog, int id) {

               finish();

           }

       });

       builder.create().show();

   }



   //여기부터는 GPS 활성화를 위한 메소드들

   private void showDialogForLocationServiceSetting() {


       AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

       builder.setTitle("위치 서비스 비활성화");

       builder.setMessage("앱을 사용하기 위해서는 위치 서비스가 필요합니다.\n"

               + "위치 설정을 수정하실래요?");

       builder.setCancelable(true);

       builder.setPositiveButton("설정", new DialogInterface.OnClickListener() {

           @Override

           public void onClick(DialogInterface dialog, int id) {

               Intent callGPSSettingIntent

                       = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);

               startActivityForResult(callGPSSettingIntent, GPS_ENABLE_REQUEST_CODE);

           }

       });

       builder.setNegativeButton("취소", new DialogInterface.OnClickListener() {

           @Override

           public void onClick(DialogInterface dialog, int id) {

               dialog.cancel();

           }

       });

       builder.create().show();

   }



   @Override

   protected void onActivityResult(int requestCode, int resultCode, Intent data) {

       super.onActivityResult(requestCode, resultCode, data);


       switch (requestCode) {


           case GPS_ENABLE_REQUEST_CODE:


               //사용자가 GPS 활성 시켰는지 검사

               if (checkLocationServicesStatus()) {

                   if (checkLocationServicesStatus()) {


                       Log.d(TAG, "onActivityResult : 퍼미션 가지고 있음");



                       if ( mGoogleApiClient.isConnected() == false ) {


                           Log.d( TAG, "onActivityResult : mGoogleApiClient connect ");

                           mGoogleApiClient.connect();

                       }

                       return;

                   }

               }


               break;

       }

   }



}




5. 관련 포스팅


5.1. Google Maps Android API 사용 방법 및 예제

Google Maps Android API를 사용하는 기본적인  방법과 사용시 발생할 수 있는 문제점에 대해 다룹니다.

http://webnautes.tistory.com/647



5.2. Places API Web Service를 사용하여 Android Google Map에 현재 위치 주변의 음식점 표시하기


Places API Web Service를 이용하여 현재 위치 주변의 음식점 정보를 안드로이드의 구글맵에 표시하는 내용을 다룹니다.

http://webnautes.tistory.com/1080



5.3. GenyMotion 가상머신에 Google Apps설치하여 Google Maps Android API 태스트 하기


Genymotion에서 Google Map API을 가지고 작성한 Android 앱을 테스트하는 방법을 소개합니다.

http://webnautes.tistory.com/1064



저작자 표시 비영리 동일 조건 변경 허락
신고
  1. 이전 댓글 더보기
  2. 사랑합니다 2016.12.01 15:14 신고

    옛날 예제들은 다 안되더라구여 ㅠㅠ 정말 감사합니다

  3. lee 2016.12.02 12:18 신고

    안녕하세요 초보라서 따라하고있었는데 에러가 나서 질문올립니다 ㅠ

    맨위에 public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
    LocationListener, OnMapReadyCallback { 이부분이 에러가 나는데 메소드를 해줘야 하나요 세개만 추가하면 되던데 코드엔 없어서 걍 추가해놓으면 되는건가요?

    Manifest.permission.ACCESS_FINE_LOCATION , Manifest.permission.ACCESS_COARSE_LOCATION 이부분이 에러가 나는데 클래스를 만들어야 하는건가요??
    그냥 만들기만 하면 되는건지 궁금합니다.(정확히는 ACCESS_FINE_LOCATION , ACCES_COARSE_LOCATION 이쪽만 에러가 납니다)

    초보적인 질문 죄송합니다 ㅠㅠ

    • webnautes webnautes 2016.12.02 12:30 신고

      GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
      LocationListener, OnMapReadyCallback에 대한 메소드들이 모두 추가되어 있어야 합니다.

      그래서 첫번째 줄에서 에러나는 것입니다. 첫번째 줄에 마우스로 클릭해보면 빨간색 느낌표가 보일텐데 선택하면 자동으로 필요한 메소드들을 모두 추가 해줄겁니다.


      Manifest.permission.ACCESS_FINE_LOCATION 앞에 android를 붙이세요.. 아래처럼

      android.Manifest.permission.ACCESS_FINE_LOCATION

  4. 권다현 2016.12.04 00:28 신고

    정말 감사합니다
    엄청 도움됬어요 ^^
    현재위치 주변의 음식점에 마커를 표시하고 싶은데 어떻게 해야하나요?? ㅠㅠ
    http://rammuking.tistory.com/entry/Android-Google-Places-API-Web-Service-%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95-%EC%A3%BC%EB%B3%80%EA%B2%80%EC%83%89
    참고해서
    @Override
    public void onLocationChanged(Location location) {
    안에
    cGPlacesAPI places = new cGPlacesAPI(this, location.getLatitude(), location.getLongitude(), "food|restaurant");
    하면 앱이 중지되요 ㅠㅠ

    • webnautes webnautes 2016.12.04 12:14 신고

      새로 추가된 포스팅이 있습니다...
      참고하시길

      Places API Web Service를 사용하여 Google Map에 현재 위치 주변의 음식점 표시하기
      http://webnautes.tistory.com/1080

  5. 질문!! 2016.12.26 18:01 신고

    구글 API클라이언트로 GPS정보를 얻어올려면 locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER 이부분이 반드시 실행되어야 하나요??

    또 locationManager의 현재 코드에서 어떤 역할인지가 궁금합니다

    • webnautes webnautes 2016.12.26 18:13 신고

      사용자가 gps를 비활성화시켜놓고 앱을 실행시켰을때 gps를 활성화시키기 위한 코드의 일부입니다..

    • 질문!! 2016.12.28 09:46 신고

      항상 글 잘보고 있습니다. 답변 감사합니다.

  6. 초보개발자 2016.12.28 14:53 신고

    이부분을 프레그먼트에서 구현하고 싶은데 어떻게 해야하죠??

    참조할 링크라도 알려주시면 감사하겠습니다.

    • webnautes webnautes 2016.12.28 15:01 신고

      github에서 찾아보는수밖에 없을거 같습니다..

    • webnautes webnautes 2016.12.28 15:05 신고

      프래그먼트랑 관련 콜백함수만 공부하셔서 직접 프로그래밍 하셔도 될듯하내요..

    • 초보개발자 2016.12.28 17:47 신고

      프레그먼트로 구현하긴 했는데 gps를 설정하고 뒤로가기를 누르면 오류가 뜹니다 ㅠㅠ
      onActivityResult부분이 문제인거 같은데 힌트좀 주실수 있으신가요??

    • webnautes webnautes 2016.12.28 17:52 신고

      프래그먼트로는 저도 안해봐서.. github에서 찾아보시는게 좋을듯합니다..

    • webnautes webnautes 2016.12.28 18:03 신고

      혹시 MainActivity.this사용한부분에서 에러나지 않았나요?

    • 초보개발자 2016.12.28 18:15 신고

      //GPS 활성화를 위한 다이얼로그
      private void showGPSDisabledAlertToUser()
      {
      AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
      alertDialogBuilder.setMessage("GPS가 비활성화 되어있습니다. 활성화 할까요?")
      .setCancelable(false)
      .setPositiveButton("설정", new DialogInterface.OnClickListener()
      {
      public void onClick(DialogInterface dialog, int id)
      {
      Intent callGPSSettingIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
      //onActivityResult 함수에 GPS설정화면과 인트값을 넘겨주고 실행시킴
      getActivity().startActivityForResult(callGPSSettingIntent, REQUEST_CODE_GPS);
      }
      });

      alertDialogBuilder.setNegativeButton("취소", new DialogInterface.OnClickListener()
      {
      public void onClick(DialogInterface dialog, int id)
      {
      dialog.cancel();
      }
      });
      AlertDialog alert = alertDialogBuilder.create();
      alert.show();
      }

      //다이얼로그의 결과 처리
      @Override
      public void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult (requestCode, resultCode, data);

      switch (requestCode) {
      case REQUEST_CODE_GPS:
      //Log.d(TAG,""+resultCode);
      //if (resultCode == RESULT_OK)
      //사용자가 GPS 활성 시켰는지 검사
      if ( locationManager == null)
      locationManager = (LocationManager) getActivity().getSystemService(LOCATION_SERVICE);

      if ( locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
      {
      // GPS 가 ON으로 변경되었을 때의 처리.
      setGPS = true;

      mapFragment.getMapAsync(this);
      }
      break;
      }
      }
      지금 코드상으로는 오류나는 부분이 하나도 없습니다.

    • webnautes webnautes 2016.12.28 19:18 신고

      http://stackoverflow.com/a/33525515 만 조심하시면 문제없이 될듯합니다...

      onCreateView 콜백 메소드에서 아래처럼만 해주면 됩니다.

      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

      View view = inflater.inflate(R.layout.fragment, container, false);

      locationManager = (LocationManager) getActivity().getSystemService(LOCATION_SERVICE);

      //minSdkVersion 17 이상 필요
      mapFragment = (MapFragment) this.getChildFragmentManager().findFragmentById(R.id.map);
      mapFragment.getMapAsync(this);

      return view;
      }

    • 초보개발자 2016.12.29 10:25 신고

      감사합니다 ㅠㅠ 작동되네요...
      제가 oncreateview에서 맵뷰 사용해 놓고 onactivityResult에서는 코드를 그대로 사용했네요 ㅠㅠ

  7. 초보개발자 2017.01.02 16:57 신고

    저 죄송한데 한가지더 여쭙고 싶은게 있습니다.
    if ( locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
    setGPS = true;

    mLocationRequest = new LocationRequest();
    //mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
    mLocationRequest.setInterval(1000);
    mLocationRequest.setFastestInterval(1000);

    onConneected에서 이부분 if문만 있는데 잘못하신 건지 아니면 다른 의도가 있는건지 궁금합니다.

  8. buster 2017.02.25 11:35 신고

    초보개발자님 성공하셨나요? 저도 프래그먼트로 구현중인데 오류가 나서...
    처음 한번은 잘 불러와지는데 두번째 불러올때

    E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.map, PID: 4015
    android.view.InflateException: Binary XML file line #14: Error inflating class fragment
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:763)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
    at com.example.trevelimage.MapFragment.onCreateView(MapFragment.java:141)
    at android.support.v4.app.Fragment.performCreateView(Fragment.java:2189)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1299)
    at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595)
    at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:757)
    at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2355)
    at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2146)
    at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2098)
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2008)
    at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:710)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5254)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
    Caused by: java.lang.IllegalArgumentException: Binary XML file line #14: Duplicate id 0x7f0f0104, tag null, or parent id 0xffffffff with another fragment for com.google.android.gms.maps.MapFragment
    at android.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2120)
    at android.app.Activity.onCreateView(Activity.java:5328)
    at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:36)
    at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:79)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:733)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:806) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:504) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:414) 
    at com.example.map.MapFragment.onCreateView(MapFragment.java:141) 
    at android.support.v4.app.Fragment.performCreateView(Fragment.java:2189) 
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1299) 
    at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528) 
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595) 
    at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:757) 
    at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2355) 
    at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2146) 
    at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2098) 
    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2008) 
    at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:710) 
    at android.os.Handler.handleCallback(Handler.java:739) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:135) 
    at android.app.ActivityThread.main(ActivityThread.java:5254) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 

    라고 떠서요;;

    저거대로 따라가보면 onCreateView의 View view = inflater.inflate(R.layout.fragment_map,container,false); 이게 문제라고 나오는데...
    아예 실행이 안되면 모르겠는데 한번은 되는데 두번째에서 안되니 당황스럽네요;;

  9. ParkJ 2017.03.07 16:29 신고

    안녕하세요 도움많이 되었습니다 ㅎㅎ
    그런데 궁금한게 있는데여 ~
    소스 중에 보시면
    ===========================================================================================
    //퍼미션 요청을 위해 UI를 보여줘야 하는지 검사
    if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.ACCESS_FINE_LOCATION)) {
    // Show an expanation to the user *asynchronously* -- don't block
    // this thread waiting for the user's response! After the user
    // sees the explanation, try again to request the permission.

    //Prompt the user once explanation has been shown;
    requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE_LOCATION);

    } else
    //UI보여줄 필요 없이 요청
    requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE_LOCATION);
    ==========================================================================================
    라고 권한 체크하는 부분이 있는데 현재 if문 안에있는 로직과 else 문 안에 있는 로직이
    requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE_LOCATION);
    위에 부분 처럼 동일한데 .. 이게 맞는건가여? if 문의 필요성이 없어지는 것같아서...ㅋ..

    • webnautes webnautes 2017.03.07 17:51 신고

      권한요청 거부하고 앱을 종료했다가 다시 앱을 실행시켰을때 다이얼로그를 하나 더 띄워서 지난번에 거부했던 퍼미션을 허가해야 한다고 알려주는 용도로 사용되는데...

      없어도 무방할듯 하긴 합니다만... 포스팅 코드에는 사용했을 경우로 수정해놓았습니다...


      말씀하신대로 아래 한줄만 있어도 됩니다...
      requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE_LOCATION);


  10. ParkJ 2017.03.08 11:09 신고

    onLocationChanged 부분은 계속 호출이 되는 것 같네여
    현재 위치 주소가 계속 토스트로 몇초에 한번씩계속 출력되네여.. ( 토스트가 사라지면 바로 다시 토스트가 출력됨)

    그리고 현재 위치에서 손으로 밑으로 내리거나 위로 올리거나 움직이면 거기에 있어야 하는데 다시 현재위치로 잡혀버리네여 .. ㄷㄷ

    • webnautes webnautes 2017.03.08 11:17 신고

      가까운 거리에서 움직이는건 오류가 발생할수 있습니다.. 먼거리 이동으로 확인해보세요..

      너무 자주 업데이트 되는거 같으면 지도를 업데이트하는 주기를 변경하면 됩니다..setInterval 함수와
      setFastestInterval를 인자 를 조정하세요..

    • ParkJ 2017.03.08 11:27 신고

      감사합니다 ㅎㅎ
      어느 시점에 업데이트를 해주는게 가장 좋을까여? ( 10분?)

      어짜피 지역이 변경된다면 LocationChange() 메소드가 호출 될 꺼니깐 업데이트 인터벌은 10분 정도 해두는 게 무방하겠져?

    • webnautes webnautes 2017.03.08 11:34 신고

      사용하시려는 용도에 맞게 조정 하셔야되요

      테스트해보고 정하셔야 할듯하네요

  11. ParkJ 2017.03.08 15:43 신고

    답변 감사드립니다.

    로직을 보다가 궁금해졌는데 만약에 현재위치(서울) 에서 다른위치(부산)를 보다가 현재위치 버튼을 클릭 시 다시 현재위치를 볼 수 있게끔 하려면
    GoogleClientAPI를 reconnect 해도 괜찮을 까여? 아니면 disconnected를 하고 connected를 하는게 맞을까여..?
    혹시 다른 방법이 있을까여?
    (현재 소스 기준입니다)

    • ParkJ 2017.03.08 15:45 신고

      현재 테스트해본결과 reconnected를 하면 현재위치로 돌아오기는 하는데
      어짜피 connected 메소드를 다시 호출하는 것이니깐 권한체크 및 마커는 문제 없을 것이라고 판단이 되어집니다.
      혹시 다른 문제가 있을까여?

    • ParkJ 2017.03.08 15:52 신고

      하지만 GPS를 꺼버리면 아무런 동작을 안하네여...어느시점부터 다시 시작을 해야할 지... onMapReady부터 다시해야할지..갑자기 난감해지는...ㄷㄷ

    • webnautes webnautes 2017.03.08 16:50 신고

      지도의 오른쪽 상단에 있는 My Location 버튼을 눌렀을 경우의 처리를 위해서 checkLocationPermission() 메소드에 다음 코드가 추가되어 있습니다. 다른 지역을 보다가 My Location 버튼을 누르면 현재 위치로 돌아오게 됩니다. 정확한 추가 위치는 포스팅에 있는 MainActivity.java 코드를 확인하세요..
      googleMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() {

      @Override
      public boolean onMyLocationButtonClick() {
      mGoogleApiClient.reconnect();

      return true;
      }
      });

    • webnautes webnautes 2017.03.08 16:53 신고

      보통 앱이 시작할때에 GPS가 꺼져있는지 체크해서 사용자에게 GPS 활성화를 물어보는 다이얼로그를 띄우는데....

      앱이 이미 시작한 상태에서 처리할려면...
      지도의 오른쪽 상단에 있는 My Location 버튼을 눌렀을 경우 GPS 활성화를 물어보는 창을 띄우는 수밖에 없습니다...

      위에 답변드린 아래 코드부분에서 onMyLocationButtonClick메소드에 추가해야 합니다..
      googleMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() {

      @Override
      public boolean onMyLocationButtonClick() {
      mGoogleApiClient.reconnect();

      return true;
      }
      });

  12. kim 2017.03.22 17:42 신고

    어플이 실행되지않고 바로 꺼지는데 이유가 뭘까요?

    • webnautes webnautes 2017.03.22 20:54 신고

      제가 포스팅할때 생각지 못한 퍼미션 경우의 수땜에 그럴 수도 있습니다..

      앱을 삭제한 후 다시 해보세요..

      포스팅에 있는 코드를 개선한 버전을 만들었는데 아직 확인 및 문서화 중 입니다..

    • webnautes webnautes 2017.03.22 20:56 신고

      이번주 주말 내로 수정한 코드를 가지고 포스팅 내용을 수정할 예정입니다..

    • webnautes webnautes 2017.03.26 21:42 신고

      런타임 퍼미션관련 코드가 문제인듯 싶어서 수정했습니다..

      혹시 안드로이드 6.0 미만 버전으로 태스트 하신건 아닌지요? 제가 이 버전대는 폰이 없어서 아직 태스트를 못해봤습니다.

    • webnautes webnautes 2017.03.27 11:31 신고

      킷캣(안드로이드 4.4) 이하 버전 사용시에도 문제가 있네요.. 다음 포스팅을 참고하세요..

      Android KitKat(4.4) 이하 버전에서 Google Map 사용시 Unable to get provider com.google.firebase.provider.FirebaseInitProvider

      http://webnautes.tistory.com/1123

  13. 초보개발자 2017.04.12 15:28 신고

    질문이 있는데요 여기서 처음에 기본 디폴트 위치 뜨고나서 제 위치로 가는데 바로 제위치를 띄울수는 없나요??

    • webnautes webnautes 2017.04.12 16:19 신고

      처음에 현재 위치를 찾는데 시간이 걸립니다... 이건 어쩔수 없는 듯합니다..

      그래서 전 서울로 초기위치를 잡아준건대..

      다른 방법은 마지막에 안드로이드폰이 위치를 인식했던 정보를 가져오는 방법이 있습니다.

      아래 링크를 참고하세요..
      https://developer.android.com/training/location/retrieve-current.html

    • 초보개발자 2017.04.12 21:34 신고

      봤는데 onCreate에 onConnected 를 넣으란 말인가요?? 바도 잘 모르겟네요 ㅠㅠ

    • webnautes webnautes 2017.04.13 18:06 신고

      다음 예제코드에서 onConnected메소드를 참고하세요
      https://github.com/googlesamples/android-play-location/blob/master/BasicLocationSample/app/src/main/java/com/google/android/gms/location/sample/basiclocationsample/MainActivity.java

  14. 안드로이드 2017.05.05 19:44 신고

    처음 실행했을 때 제 위치를 제대로 인식 하지 못 합니다. 그리고 그 다음 부터는 다 서울역으로 뜹니다. 위치를 알 수 없다고 해요. 혹시 이거 왜 이러는지 아시나요?

  15. 안드로이드 2017.05.08 14:49 신고

    4.4 키켓이요

    • webnautes webnautes 2017.05.08 20:54 신고

      코드를 수정했습니다..

      4.4.4 킷캣 사용하는 폰에서 태스트해보기했는데..

      문제 있으면 알려주세요..

  16. 안드로이드 2017.05.09 17:44 신고

    문제 없습니다. 감사합니다.

  17. yse00501 2017.05.16 20:28 신고

    안녕하세요 작성자님 덕분에 map에 대해서 쉽게 접근하게 되었습니다. 감사합니다.

    gps설정을 하기 전에 defualt값으로 서울을 찍고 gps를 받기 시작하면 마커를 현재위치로 옮겨찍게 되는데
    혹시 몇몇 위치에 무조건 마커를 남겨두게 하고 싶다면 어떤 방법으로 해야하는지 여쭤봐도 될까요???

    또한 이 마커들을 특정 위치반경 이내에서만 보이게 할 수 있나요?? (예를들면 반경 1km이내의 마커만 보이게 하기)

    • webnautes webnautes 2017.05.17 20:55 신고

      포스팅의 코드를 보면 setCurrentLocation 메소드에서


      현재 마커가 이전에 생성되어 지도에 표시되어 있다면 삭제를 먼저합니다.
      if (currentMarker != null) currentMarker.remove();


      그리고 다음처럼해서 현재위치 마커를 지도에 표시합니다.
      currentMarker = mGoogleMap.addMarker(markerOptions);

      setCurrentLocation 메소드를 참고하여
      원하는 위치에 마커를 추가하시면 사라지지 않고 계속 남게 됩니다.

      특정 거리내에 있는 마커만 표시하는 메소드가 google map API에 없는듯 합니다.

      현재 위치에서 특정 범위 내에 있는 마커들을 좌표가지고 계산해줘야 할거 같은데.. 다른 방법이 있을 수도 있습니다.

  18. :) 2017.05.28 16:25 신고

    안녕하세요 선생님
    편안한 주말 보내고 계시나요?!
    자세하고 친절한 글 정말 감사합니다 도움이 정말 많이됬어요..
    그럼에도 불구하고 제 실력이 많이 부족해서
    Google Maps Android API 사용 방법 및 예제까지는 완벽하게 했는데
    이 예제는 에러도 하나도 없고 실행이 되는데 서울 한국의 수도만 뜨고 현재 위치가 나오질 않네요..ㅠㅠ 뭐가 문제인지 모르겠어요..
    Android 7.0(Google play)버전 사용중입니다!

    • webnautes webnautes 2017.05.29 14:09 신고

      Android 7.0을 사용하는 안드로이드폰으로 테스트 해봤는데 코드에도 문제가 없고 동작도 정상적으로 됩니다..

      혹시 테스트할 때 에뮬레이터를 사용한건가요?

    • :) 2017.05.29 14:49 신고

      아.... 제가 폰으로 연결이안되서 애뮬레이터에서 밖에못해봤어요 그래서그랬던건가요..?!
      두번째로 올린글(소스)은 보셨고 자리만 차니하니까 지울게요!

    • :) 2017.05.29 15:01 신고

      선생님 그러면
      제가 만들고 있는 어플중에 '위치찾기' 버튼을 누르면 이 예제가 실행되기를 원하는데 그렇게 하려면 어떻게해야하나요?..
      간단히라도 좋으니 설명 좀 부탁드립니다..!!

    • webnautes webnautes 2017.05.29 15:11 신고

      안드로이드폰으로 해보셔야 합니다..

      윈도우에서 안드로이드폰이 USB 메모리처럼 잡히지 않나요?

      그렇다면 연결 방법을 MTP(파일)가 아닌 PTP(사진)로 변경하고 안드로이드 스튜디오를 켠 상태에서 다시 연결해보세요


      다음 포스팅에서 안드로이드 디바이스에서 앱 실행 항목을 확인해보세요..
      http://webnautes.tistory.com/1126

    • webnautes webnautes 2017.05.29 22:22 신고

      Android Emulator로는 자세한 기능을 아직 모르겠네요..

      찾아보니 Gnymotion으로는 테스트 해본적이 있었네요..

      http://webnautes.tistory.com/1064

    • :) 2017.05.29 22:59 신고

      넵 감사합니다~!! ^^*!

  19. yse00501 2017.06.01 22:04 신고

    안녕하세요 작성자님!!
    궁금한 질문 몇가지 부탁드리겠습니다

    현재 위치를 제외하고 원하는 위치에 마커를 몇개 찍어놓은 상태입니다. 그런데 현재위치에서 표시되는 반경원의 범위를 1km로 늘리고 싶은데 방법이 있나요???

    • webnautes webnautes 2017.06.02 07:17 신고

      아래 링크를 확인해보세요.
      https://stackoverflow.com/questions/36030648/custom-disabled-and-blank-map-in-android/36039979#36039979

  20. pjaen 2017.08.08 01:57 신고

    안녕하세요 이 소스코드는 주기적으로 지도가 업데이트 되는데 업데이트 안되는 방법 없나요?! 내위치눌렀을때만 내 위치를 찾아주게끔요!

    • webnautes webnautes 2017.08.08 16:48 신고

      onLocationChanged 메소드에 if문을 추가하여 특정 변수가 true일 때에만 업데이트되개 하면 될듯해요.


      버튼 클릭할때마다 변수를 true로 해주면 될듯합니다.

      if문에서 true 조건이면 바로 해당 변수를 false로 해줘야합니다.

  21. 기초공부중 2017.08.09 08:10 신고

    지도화면 뜨는데 꽤 오랜시간이 걸리군요 ㅠ

    이동할때 자기가 걸어온 곳을 실시간으로 Polyline 을 써서 표시하고 싶은데 어느곳에 소스를 삽입하면되나요?

+ Recent posts

티스토리 툴바