ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Places API Web Service를 사용하여 Android Google Map에 현재 위치 주변의 음식점 표시하기
    Android/Google Map 2019.08.15 11:00





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



    Google Maps Android API를 사용하는 방법과  FusedLocationProviderClient 를 이용하여 현재 위치를 구글맵에 표시하는 내용을 다음 두 포스팅에서 다루었습니다.

    중복된 내용은 빠져있기 때문에 본 포스팅에 있는 내용을 진행하기 전에 미리 검토해보세요..

     

    Google Maps Android API 사용 방법 및 예제

    http://webnautes.tistory.com/647 


    Android Google Map에 현재 위치 표시하기( FusedLocationProviderClient 사용)

    https://webnautes.tistory.com/1249 




     2016.12. 4

     2017.11.27  주변 장소의 주소가 한글로 나오도록 수정

     2018. 6. 13 

     2019. 7. 19  FusedLocationProviderClient 사용하도록 수정

     2019. 8. 15  androidx,SupportMapFragment 사용하도록 수정





    1. Places API Web Service 키 얻기


    2. Google Map에 현재 위치 주변의 음식점 표시하기


    3. 실행 결과


    4. 구현시 참고





    Places SDK for Android v.3.0.0 BETA를 테스트해보았습니다. 

    안드로이드에서도 현재 위치를 기준으로 타입별로 장소를 검색할 수 있게 됩니다.

    얼른 정식 버전이 나왔으면 좋겠군요.


    Places SDK for Android v.3.0.0 BETA 사용해보기

    https://webnautes.tistory.com/1370



    1. Places API Web Service 키 얻기

    현재 위치 주변에 있는 장소를 종류별로 검색하는 기능을 Google Places API for Android에서는 아직 제공하지 않기 때문에 Places API Web Service를 사용합니다.


    1. Google Developers Console 사이트(https://console.developers.google.com/flows/enableapi?apiid=places_backend&reusekey=true&hl=ko )에 접속합니다. 




    2. 콤보박스를 클릭하여 Google Maps Android API를 위해 생성했던 프로젝트를 선택하고 계속을 클릭합니다.  





    3. 어떤 사용자 인증 정보가 필요한가요?를 클릭합니다.





    4. 생성된  API키를 복사해두고 완료를 클릭합니다. 





    5. 이제 프로젝트에 Places API Web Service를 위한 API 키와 Google Maps Android API를 위한 API키  두 개가 존재합니다. 





    2. Google Map에 현재 위치 주변의 음식점 표시하기

    Places API Web Service에서 제공하는 REST API를 사용하여 현재 위치 주변의 음식점에 대한 정보를 요청하여 획득된 JSON을 파싱하는 작업을 해주면  되지만 여기에서는 간단하게 구현이 가능한 Android-Google-Places-API 라이브러리(https://github.com/nomanr/Android-Google-Places-API)를 사용했습니다.



    다음 포스팅에 있는 코드를 기반으로 수정하는 방법을 설명합니다.


    Android Google Map에 현재 위치 표시하기( FusedLocationProviderClient 사용)

    https://webnautes.tistory.com/1249 



    레이아웃 파일( activity_main.xml )에 버튼을 추가하고 android:layout_weight 속성으로 화면에 보이는 지도와 버튼의 높이를 조정합니다. 


    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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"
        android:id="@+id/layout_main"
        android:orientation="vertical"
       tools:context=".MainActivity" >

        <fragment
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.8"
            android:id="@+id/map"
            tools:context=".MapsActivity"
            android:name="com.google.android.gms.maps.SupportMapFragment" />

        <Button
            android:text="장소검색"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.2"
            android:id="@+id/button"/>

    </LinearLayout>



    app 모듈을 위한 build.gradle 파일에서  minSdkVersion15 이상으로 사용해야 합니다. 


    android {
        compileSdkVersion 29
        buildToolsVersion "29.0.2"
        defaultConfig {
            applicationId "com.tistory.webnautes.googlemaptest"
            minSdkVersion 21
            targetSdkVersion 29
           versionCode 1
            versionName "1.0"
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        }



    Android-Google-Places-API 라이브러리를 추가해줍니다.  글 작성시점에서 최신 버전은 1.1.3입니다.


    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'androidx.appcompat:appcompat:1.0.2'
        implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
        implementation 'com.google.android.gms:play-services-maps:17.0.0'
        implementation 'com.google.android.gms:play-services-location:17.0.0'
        implementation 'com.google.android.material:material:1.1.0-alpha09'
        implementation 'noman.placesapi:placesAPI:1.1.3'
       testImplementation 'junit:junit:4.12'
        androidTestImplementation 'androidx.test:runner:1.2.0'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    }



    변경된 사항을 반영해주기 위해 상단 우측에 보이는  Sync Now를 클릭합니다.




    다음과 같은 에러가 발생합니다.


    Manifest merger failed : Attribute application@allowBackup value=(true) from AndroidManifest.xml:7:9-35
    is also present at [noman.placesapi:placesAPI:1.1.3] AndroidManifest.xml:12:9-36 value=(false).
    Suggestion: add 'tools:replace="android:allowBackup"' to <application> element at AndroidManifest.xml:6:5-27:19 to override.



    메니패스트 파일(AndroidManifest.xml)에서 <application> 태그의 allowBackup 속성을 false로 수정하면 해결됩니다.


        <application
            android:allowBackup="false"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">



    관련 내용은 다음 블로그 글을 확인해보세요. 


    안드로이드 보안 취약 점 allowBackup - 비밀 정보 쉽게 빼내어 가는 법

     http://comostudio.tistory.com/85 




    MainActivity에서 PlacesListener 인터페이스를 구현해줘야 합니다.

    PlacesListener를 추가해줍니다.


    public class MainActivity extends AppCompatActivity
            implements
            OnMapReadyCallback,
            ActivityCompat.OnRequestPermissionsResultCallback,
            PlacesListener{




    다음 세 줄을 추가해줍니다.


    import noman.googleplaces.Place;
    import noman.googleplaces.PlacesException;
    import noman.googleplaces.PlacesListener;




    추가한 인터페이스에서 요구하는 다음 4개의 메소드를 추가해줍니다.

    @Override
    public void onPlacesFailure(PlacesException e) {

    }

    @Override
    public void onPlacesStart() {

    }

    @Override
    public void onPlacesSuccess(List<Place> places) {

    }

    @Override
    public void onPlacesFinished() {

    }



    필요한 변수를 추가해줍니다.


    List<Marker> previous_marker = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);





    onPlacesSuccess 메소드의 파라미터 타입에 final을 추가해주고 다음 코드를 입력합니다.


    @Override
    public void onPlacesSuccess(final List<Place> places) {

          runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    for (noman.googleplaces.Place place : places) {

                        LatLng latLng
                                = new LatLng(place.getLatitude()
                                , place.getLongitude());

                        String markerSnippet = getCurrentAddress(latLng);

                        MarkerOptions markerOptions = new MarkerOptions();
                        markerOptions.position(latLng);
                        markerOptions.title(place.getName());
                        markerOptions.snippet(markerSnippet);
                        Marker item = mMap.addMarker(markerOptions);
                        previous_marker.add(item);

                    }

                    //중복 마커 제거
                    HashSet<Marker> hashSet = new HashSet<Marker>();
                    hashSet.addAll(previous_marker);
                    previous_marker.clear();
                    previous_marker.addAll(hashSet);

                }
            });

    }



    showPlaceInformation() 메소드를 추가해줍니다. 

     "Places API Web Service 키" 부분에 따로 복사해둔 키를 입력하셔야 합니다.


    public void showPlaceInformation(LatLng location)
    {
    mMap.clear();//지도 클리어

    if (previous_marker != null)
    previous_marker.clear();//지역정보 마커 클리어

    new NRPlaces.Builder()
    .listener(MainActivity.this)
    .key("Places API Web Service 키")
    .latlng(location.latitude, location.longitude)//현재 위치
    .radius(500) //500 미터 내에서 검색
    .type(PlaceType.RESTAURANT) //음식점
    .build()
    .execute();
    }





    onCreate 메소드에  ArrayList 초기화와 버튼 클릭시 showPlaceInformation() 메소드를 호출하는 코드를 추가합니다.



    setContentView(R.layout.activity_main);


    previous_marker = new ArrayList<Marker>();

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



    3. 실행 결과

    실행하면 현재 위치가 지도에 표시됩니다.


    주변 영역이 많이 보이도록 지도의 줌을 적당하게 조정한 후,  장소 검색 버튼을 누르면 현재 위치 주변의 음식점 위치들이 지도에 표시됩니다.


    결과를 가져오는데 좀 시간이 걸립니다. 





    음식점 위치를 표시하는 마커 하나를 선택하면 음식점 이름과 주소가 나타납니다.

    장소 검색버튼을 다시 누르면 기존 마커들을 다지우고 새로 음식점 마커들을 표시합니다.




    4. 구현시 참고

    https://developers.google.com/places/web-service/supported_types?hl=ko 에 있는 Places API Web Service에서 지원되는 장소 유형을  Android-Google-Places-API 라이브러리에서 다음처럼 정의해놓고 있습니다. 

    package noman.googleplaces;

    /**
    * Created by Noman on 8/25/2016.
    * https://developers.google.com/places/supported_types
    */
    public interface PlaceType {
        public String ACCOUNTING = "accounting";
        public String AIRPORT = "airport";
        public String AMUSEMENT_PARK = "amusement_park";
        public String AQUARIUM = "aquarium";
        public String ART_GALLERY = "art_gallery";
        public String ATM = "atm";
        public String BAKERY = "bakery";
        public String BANK = "bank";
        public String BAR = "bar";
        public String BEAUTY_SALON = "beauty_salon";
        public String BICYCLE_STORE = "bicycle_store";
        public String BOOK_STORE = "book_store";
        public String BOWLING_ALLEY = "bowling_alley";
        public String BUS_STATION = "bus_station";
        public String CAFE = "cafe";
        public String CAMPGROUND = "campground";
        public String CAR_DEALER = "car_dealer";
        public String CAR_RENTAL = "car_rental";
        public String CAR_REPAIR = "car_repair";
        public String CAR_WASH = "car_wash";
        public String CASINO = "casino";
        public String CEMETERY = "cemetery";
        public String CHURCH = "church";
        public String CITY_HALL = "city_hall";
        public String CLOTHING_STORE = "clothing_store";
        public String CONVENIENCE_STORE = "convenience_store";
        public String COURTHOUSE = "courthouse";
        public String DENTIST = "dentist";
        public String DEPARTMENT_STORE = "department_store";
        public String DOCTOR = "doctor";
        public String ELECTRICIAN = "electrician";
        public String ELECTRONICS_STORE = "electronics_store";
        public String EMBASSY = "embassy";
        public String FINANCE = "finance";
        public String FIRE_STATION = "fire_station";
        public String FLORIST = "florist";
        public String FUNERAL_HOME = "funeral_home";
        public String FURNITURE_STORE = "furniture_store";
        public String GAS_STATION = "gas_station";
        public String GYM = "gym";
        public String HAIR_CARE = "hair_care";
        public String HARDWARE_STORE = "hardware_store";
        public String HINDU_TEMPLE = "hindu_temple";
        public String HOME_GOODS_STORE = "home_goods_store";
        public String HOSPITAL = "hospital";
        public String INSURANCE_AGENCY = "insurance_agency";
        public String JEWELRY_STORE = "jewelry_store";
        public String LAUNDRY = "laundry";
        public String LAWYER = "lawyer";
        public String LIBRARY = "library";
        public String LIQUOR_STORE = "liquor_store";
        public String LOCAL_GOVERNMENT_OFFICE = "local_government_office";
        public String LOCKSMITH = "locksmith";
        public String LODGING = "lodging";
        public String MEAL_DELIVERY = "meal_delivery";
        public String MEAL_TAKEAWAY = "meal_takeaway";
        public String MOSQUE = "mosque";
        public String MOVIE_RENTAL = "movie_rental";
        public String MOVIE_THEATER = "movie_theater";
        public String MOVING_COMPANY = "moving_company";
        public String MUSEUM = "museum";
        public String NIGHT_CLUB = "night_club";
        public String PAINTER = "painter";
        public String PARK = "park";
        public String PARKING = "parking";
        public String PET_STORE = "pet_store";
        public String PHARMACY = "pharmacy";
        public String PHYSIOTHERAPIST = "physiotherapist";
        public String PLUMBER = "plumber";
        public String POLICE = "police";
        public String POST_OFFICE = "post_office";
        public String REAL_ESTATE_AGENCY = "real_estate_agency";
        public String RESTAURANT = "restaurant";
        public String ROOFING_CONTRACTOR = "roofing_contractor";
        public String RV_PARK = "rv_park";
        public String SCHOOL = "school";
        public String SHOE_STORE = "shoe_store";
        public String SHOPPING_MALL = "shopping_mall";
        public String SPA = "spa";
        public String STADIUM = "stadium";
        public String STORAGE = "storage";
        public String STORE = "store";
        public String SUBWAY_STATION = "subway_station";
        public String SYNAGOGUE = "synagogue";
        public String TAXI_STAND = "taxi_stand";
        public String TRAIN_STATION = "train_station";
        public String TRANSIT_STATION = "transit_station";
        public String TRAVEL_AGENCY = "travel_agency";
        public String UNIVERSITY = "university";
        public String VETERINARY_CARE = "veterinary_care";
        public String ZOO = "zoo";

    }



    showPlaceInformation() 메소드에서 PlaceType.RESTAURANT를 필요시 위에 나온 원하는 타입으로 바꾸시면 됩니다. 

    public void showPlaceInformation(LatLng location)
    {
    mGoogleMap.clear();//지도 클리어

    if (previous_marker != null)
    previous_marker.clear();//지역정보 마커 클리어

    new NRPlaces.Builder()
    .listener(MainActivity.this)
    .key("Places API Web Service 키")
    .latlng(location.latitude, location.longitude)//현재 위치
    .radius(500) //500 미터 내에서 검색
    .type(PlaceType.RESTAURANT) //음식점

                      .language("ko", "KR")
    .build()
    .execute();
    }



    .type(PlaceType.RESTAURANT)를 지우면 주변에 있는 모든 타입의 장소가 검색됩니다.




    포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
    댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

    여러분의 응원으로 좋은 컨텐츠가 만들어집니다. 지금 본 내용이 도움이 되었다면 후원 또는 유튜브 구독 부탁드립니다. 감사합니다 : )

    유튜브 구 독 하 기
    후 원 하 기


    댓글 327

    • 이전 댓글 더보기
    • 2019.09.21 10:01


      앱을 실행하면 지오코더 서비스 사용불가라고 뜨면서 현재위치말고는 마커가 뜨질않네요ㅠㅠ 로그캣 보는 방법도 몰라서 헤매고있습니다... 이런 경우에는 어떻게 해야되나요..?

    • 2019.09.21 11:26


      네 폰으로 테스트중이고, 마커가 이동시 따라갑니다..혹시 무슨 문제인가요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.09.21 14:25 신고


        아는 위치에 대한 gps를 입력하여 주소가 나오나 보세요

      • 2019.09.21 14:31


        어떻게 말씀이신지...죄송합니다 제가 잘 몰라서 ㅠㅠㅠ

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.09.21 14:34 신고


        getCurrentAddress 함수 사용하는 부분을 참고하여 gps 입력시 주소가 나오나 보세요

      • 2019.09.21 15:00


        경도, 위도를 바꿔도 계속 현재 위치만 뜨네요... 지오코더가 작동을 못하는건가요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.09.21 15:02 신고


        지도 현재위치를 바꾸는 게 아니라 gps 입력시 주소가 제대로 나오는지 확인하는 겁니다. 위치 아는 gps입력시 해당 주소가 나오나 보세요

      • 2019.09.21 16:56


        네 주소는 뜨네요 근데 주변 마크가 하나도 뜨질 않습니다.

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.09.21 17:07 신고


        주변장소 보이는건 showPlaceInformation함수에 좌표를 넣으면 됩니다. 바로 보이지는 않습니다. 어느정도 기다려야 합니다

      • 2019.09.21 18:22


        package org.techtown.gps3;
        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.os.Looper;
        import android.provider.Settings;
        import android.os.Bundle;
        import android.util.Log;
        import android.view.View;
        import android.view.WindowManager;
        import android.widget.Button;
        import android.widget.Toast;

        import androidx.annotation.NonNull;
        import androidx.annotation.Nullable;
        import androidx.appcompat.app.AlertDialog;
        import androidx.appcompat.app.AppCompatActivity;
        import androidx.core.app.ActivityCompat;
        import androidx.core.content.ContextCompat;

        import com.google.android.gms.common.ConnectionResult;
        import com.google.android.gms.common.api.GoogleApiClient;
        import com.google.android.gms.location.FusedLocationProviderClient;
        import com.google.android.gms.location.LocationCallback;
        import com.google.android.gms.location.LocationListener;
        import com.google.android.gms.location.LocationRequest;
        import com.google.android.gms.location.LocationResult;
        import com.google.android.gms.location.LocationServices;
        import com.google.android.gms.location.LocationSettingsRequest;
        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.ArrayList;
        import java.util.HashSet;
        import java.util.List;
        import java.util.Locale;

        import noman.googleplaces.NRPlaces;
        import noman.googleplaces.Place;
        import noman.googleplaces.PlaceType;
        import noman.googleplaces.PlacesException;
        import noman.googleplaces.PlacesListener;

        public class MainActivity extends AppCompatActivity
        implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, PlacesListener {

        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;
        private static final int FASTEST_UPDATE_INTERVAL_MS = 500;

        private AppCompatActivity mActivity;
        boolean askPermissionOnceAgain = false;
        boolean mRequestingLocationUpdates = false;
        Location mCurrentLocation;
        boolean mMoveMapByUser = true;
        boolean mMoveMapByAPI = true;
        LatLng currentPosition;

        LocationRequest locationRequest = new LocationRequest()
        .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
        .setInterval(UPDATE_INTERVAL_MS)
        .setFastestInterval(FASTEST_UPDATE_INTERVAL_MS);

        List<Marker> previous_marker =null;
        @Override
        protected void onCreate(@Nullable 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");

        previous_marker = new ArrayList<Marker>();

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


        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;

        mGoogleMap.setMyLocationEnabled(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;
        setDefaultLocation();

        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) {

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


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

        String markerTitle = getCurrentAddress(currentPosition);
        String markerSnippet = "위도:" + String.valueOf(location.getLatitude())
        + " 경도:" + String.valueOf(location.getLongitude());

        //현재 위치에 마커 생성하고 이동
        setCurrentLocation(location, markerTitle, markerSnippet);

        mCurrentLocation = 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(LatLng latlng) {

        //지오코더... GPS를 주소로 변환
        Geocoder geocoder = new Geocoder(this, Locale.getDefault());

        List<Address> addresses;

        try {

        addresses = geocoder.getFromLocation(
        latlng.latitude,
        latlng.longitude,
        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);
        }

        }


        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);


        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();
        }

        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
        public void onPlacesFailure(PlacesException e) {

        }

        @Override
        public void onPlacesStart() {

        }

        @Override
        public void onPlacesSuccess(final List<Place> places) {

        runOnUiThread(new Runnable() {

        @Override

        public void run() {

        for (noman.googleplaces.Place place : places) {


        LatLng latLng = new LatLng(place.getLatitude(), place.getLongitude());


        String markerSnippet = getCurrentAddress(latLng);


        MarkerOptions markerOptions = new MarkerOptions();

        markerOptions.position(latLng);

        markerOptions.title(place.getName());

        markerOptions.snippet(markerSnippet);

        Marker item = mGoogleMap.addMarker(markerOptions);

        previous_marker.add(item);


        }


        //중복 마커 제거

        HashSet<Marker> hashSet = new HashSet<Marker>();
        hashSet.addAll(previous_marker);
        previous_marker.clear();
        previous_marker.addAll(hashSet);
        }
        });
        }

        public void showPlaceInformation( LatLng location){
        mGoogleMap.clear();

        if(previous_marker!=null)
        previous_marker.clear();

        new NRPlaces.Builder().listener(MainActivity.this).key("AIzaSyBCSTmJ_CQMWWgL_74UKdWM9EV82sDeBME").latlng(location.latitude, location.longitude).radius(500).type(PlaceType.BANK).build().execute();
        }
        @Override
        public void onPlacesFinished() {

        }
        @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;
        }
        }


        }
        그래도... 안되서.. 코드한번만 봐주실 수 있나요..? 시간 잡아서 죄송합니다.

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.09.21 18:33 신고


        현재 위치에 마커 출력하는 포스팅에 나오는 프로그램 흐름을 보고 함수를 따라가며 어디서 문제인지 파악해보세요. 아니면 포스트의 코드에는 문제가 없으니 새 프로젝트에서 다시 해보세요.

      • 2019.09.21 18:41


        네 시간내주셔서 감사합니다

    • 2019.09.30 14:33


      장소를 식당 말고 안경점으로 변경하고 싶은데 placetype목록에 안보이면 어떻게 해야하나요?ㅠㅠ

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.09.30 17:02 신고


        목록에 없는 것은 사용할 수가 없습니다.

        다른 데이터베이스를 찾아보셔야 할듯합니다.


      • 2019.09.30 18:15


        여기에 네이버 open api 지도 위치정보를 받아와서 지도에 출력할 수 있을까요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.09.30 18:21 신고


        해보진 않아서 확실한 답변은 못드리겠네요^^;

        네이버 지도 API를 사용하는 거라면
        문제가 생기지 않을까 싶지만

        위치 정보만 제공하는 API라면 문제 없을 듯합니다.

        참고로 TourAPI라는 것도 있습니다.
        https://api.visitkorea.or.kr/about/about.do

    • 익뭉 2019.10.07 02:13


      코드 잘봤습니다. 아래는 저의 에러로그인데
      핵심은 Caused by: java.lang.IllegalArgumentException: 'restaurant' is invalid. All types are given in PlaceType
      이것 같은데 도통 감이 안잡힙니다 ...
      AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
      Process: andbook.example.locationservice, PID: 30370
      java.lang.RuntimeException: An error occurred while executing doInBackground()
      at android.os.AsyncTask$3.done(AsyncTask.java:354)
      at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
      at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
      at java.util.concurrent.FutureTask.run(FutureTask.java:271)
      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
      at java.lang.Thread.run(Thread.java:764)
      Caused by: java.lang.IllegalArgumentException: 'restaurant' is invalid. All types are given in PlaceType class
      at c.a.b.a(Unknown Source:532)
      at c.a.a.a(Unknown Source:3)
      at c.a.a.doInBackground(Unknown Source:2)
      at android.os.AsyncTask$2.call(AsyncTask.java:333)
      at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245) 
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
      at java.lang.Thread.run(Thread.java:764) 

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.07 17:53 신고


        구글 정책이 바뀌어서 안되나 싶어 다시 해보니 문제가 없었습니다.
        혹시 다음 부분에서 PlaceType.RESTAURANT를 수정했나요?


        new NRPlaces.Builder()
        .listener(MainActivity.this)
        .key("Places API Web Service 키")
        .latlng(location.latitude, location.longitude)//현재 위치
        .radius(500) //500 미터 내에서 검색
        .type(PlaceType.RESTAURANT) //음식점
        .build()
        .execute();

    • 익뭉 2019.10.08 00:19


      저의 코드입니다. 말씀해주신 부분은 큰 차이가 없습니다..

      public class MyLocationFoodActivity extends AppCompatActivity implements
      LocationListener, OnMapReadyCallback, PlacesListener {

      private FusedLocationProviderClient fusedLocationProviderClient;
      private Location location;
      private LocationRequest locationRequest;
      private GoogleMap googleMap;
      private SupportMapFragment mapFragment;
      private LatLng currentPosition;
      private Marker current_marker =null;
      private List<Marker> previous_marker = null;

      @Override
      protected void onPause(){
      super.onPause();
      // 현재 위치 따오지 않음
      if(fusedLocationProviderClient != null)
      fusedLocationProviderClient.removeLocationUpdates(locationCallback)
      .addOnCompleteListener(this, new OnCompleteListener<Void>() {
      @Override
      public void onComplete(@NonNull Task<Void> task) {
      fusedLocationProviderClient = null;
      }
      });
      }


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

      Button connect_RESTAURANT_Btn = (Button) findViewById(R.id.contact_food);

      GpsCheck.checkGPS_ON_OFF(MyLocationFoodActivity.this); // GPS 확인 유무

      getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
      WindowManager.LayoutParams.FLAG_FULLSCREEN); // 상태바 제거

      // 구글맵에 찍을 마커 Array 생성
      previous_marker = new ArrayList<Marker>();

      // 사용자 현재 위치 요청 업데이트
      locationRequest = new LocationRequest()
      .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); // 전력소모와 위치 정확도의 밸런스 고려
      LocationSettingsRequest.Builder builder =
      new LocationSettingsRequest.Builder();
      builder.addLocationRequest(locationRequest);

      // 사용자의 현재 위치 표시하기
      fusedLocationProviderClient =
      LocationServices.getFusedLocationProviderClient(MyLocationFoodActivity.this);


      // 구글맵 현재 위치 띄우기
      mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.foodMap);

      if (mapFragment != null)
      mapFragment.getMapAsync(MyLocationFoodActivity.this);


      connect_RESTAURANT_Btn.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
      googleMap.clear(); // 지도 클리어

      if (previous_marker != null)
      previous_marker.clear(); // 지역정보 마커 클리어

      Log.i("진입 food", String.valueOf(currentPosition.latitude));
      Log.i("진입 food", String.valueOf(currentPosition.longitude));
      new NRPlaces.Builder()
      .listener(MyLocationFoodActivity.this)
      .key(getApiKey.place_api_key.trim())
      .latlng(currentPosition.latitude, currentPosition.longitude)//현재 위치
      .radius(500) // 500 미터 내에서 검색
      .type(PlaceType.RESTAURANT) // 음식점
      .language("ko","KR")
      .build()
      .execute();
      }
      });
      }

      @Override
      public void onMapReady(GoogleMap map)
      {
      googleMap = map;
      // 현재 위치를 나타내기 위해 locationRequest: 사용자 위치 업데이트 완료
      // locationcallback: 현재 위치에 대한 콜백 메서드
      // Looper: 현재 처리할 쓰레드(비동기 처리)
      fusedLocationProviderClient.requestLocationUpdates(locationRequest,locationCallback, Looper.myLooper());

      googleMap.getUiSettings().setMyLocationButtonEnabled(true);
      googleMap.animateCamera(CameraUpdateFactory.zoomTo(15));
      googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
      @Override
      public void onMapClick(LatLng latLng) {
      Toast.makeText(getApplicationContext(),"runnig...",Toast.LENGTH_SHORT).show();
      }
      });
      googleMap.setMyLocationEnabled(true);
      }
      LocationCallback locationCallback = new LocationCallback(){
      @Override
      public void onLocationResult(LocationResult locationResult){
      super.onLocationResult(locationResult);
      Log.i("진입 callback","Test");
      List<Location> locationList = locationResult.getLocations();

      if(locationList.size() > 0 )
      {
      location = locationList.get(locationList.size()-1);
      currentPosition =
      new LatLng(location.getLatitude(),location.getLongitude());
      String markerTitle = getCurrentAddress(currentPosition);
      setCurrentLocation(location,markerTitle);
      }
      }
      };

      private void setCurrentLocation(Location location,String markerTitle){
      if (current_marker != null)
      current_marker.remove(); // 현재 마커 제거

      LatLng currentLatLng = new LatLng(location.getLatitude(), location.getLongitude()); // 위치 따오기

      MarkerOptions markerOptions = new MarkerOptions();
      markerOptions.position(currentLatLng);
      markerOptions.title(markerTitle);
      markerOptions.draggable(true);

      current_marker = googleMap.addMarker(markerOptions);
      CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(currentLatLng);
      googleMap.moveCamera(cameraUpdate);
      }

      // 현재 위치 주소 불러오기
      private String getCurrentAddress(LatLng latlng) {
      Geocoder geocoder = new Geocoder(this, Locale.getDefault());
      List<Address> addresses;
      try {
      addresses = geocoder.getFromLocation(
      latlng.latitude,
      latlng.longitude,
      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); // 현재 위치 한글로 변환 하여 전달
      }
      }

      // 일정시간 && 일정거리 변화 할시 호출 되는 콜백 메서드
      @Override
      public void onLocationChanged(Location location) {
      Log.i("진입 위치 변화","변화");
      currentPosition = new LatLng( location.getLatitude(), location.getLongitude() );
      String errorMessage = "";

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

      //현재 위치에 마커 생성
      LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
      MarkerOptions markerOptions = new MarkerOptions();
      markerOptions.position(latLng);
      markerOptions.title("현재위치");

      current_marker = googleMap.addMarker(markerOptions);

      //지도 상에서 보여주는 영역 이동
      googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
      googleMap.animateCamera(CameraUpdateFactory.zoomTo(15));
      googleMap.getUiSettings().setCompassEnabled(true);

      //지오코더 주소로 변환
      Geocoder geocoder = new Geocoder(this, Locale.getDefault());
      List<Address> addresses = null;
      try {
      addresses = geocoder.getFromLocation(
      location.getLatitude(),
      location.getLongitude(),
      1);
      }
      catch (IOException ioException) {
      errorMessage = "지오코더 서비스 사용불가";
      Toast.makeText( this, errorMessage, Toast.LENGTH_LONG).show();
      }
      catch (IllegalArgumentException illegalArgumentException) {
      errorMessage = "잘못된 GPS 좌표";
      Toast.makeText( this, errorMessage, Toast.LENGTH_LONG).show();
      }

      if (addresses == null || addresses.size() == 0) {
      if (errorMessage.isEmpty())
      errorMessage = "주소 미발견";;
      Toast.makeText( this, errorMessage, Toast.LENGTH_LONG).show();
      }
      else {
      Address address = addresses.get(0);
      Toast.makeText( this, address.getAddressLine(0), Toast.LENGTH_LONG).show();
      }
      }

      @Override
      public void onPlacesFailure(PlacesException e) {
      Log.i("진입 PlacesFailure", "onPlacesFailure()");
      }

      @Override
      public void onPlacesStart() {
      Log.i("진입 PlacesStart", "onPlacesStart()");
      }

      // 장소에대한 검색이 성공적으로 이뤄지면 여러장소 마커 띄우기 위한 콜백 메서드
      @Override
      public void onPlacesSuccess(final List<noman.googleplaces.Place> places) {
      Log.i("진입 PlacesSuccess", "onPlacesSuccess()");

      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      for (noman.googleplaces.Place place : places) {
      LatLng latLng = new LatLng(place.getLatitude(),
      place.getLongitude());

      MarkerOptions markerOptions = new MarkerOptions();
      markerOptions.position(latLng);
      markerOptions.title(place.getName());
      Marker item = googleMap.addMarker(markerOptions);
      previous_marker.add(item);
      }
      // 중복 마커 제거
      HashSet<Marker> hashSet = new HashSet<Marker>();
      hashSet.addAll(previous_marker);
      previous_marker.clear();
      previous_marker.addAll(hashSet);
      }
      });
      }
      @Override
      public void onPlacesFinished() {
      Log.i("진입 PlacesFinished", "onPlacesFinished()");
      }
      }

    • 익뭉 2019.10.08 02:36


      자답 입니다. 원인 찾았습니다.. 프로가드 난독화 적용한게 문제였습니다.

    • wjdwngh123 2019.10.13 16:58


      안녕하세요. 많은 도움이 되었습니다!
      올려주신 순새대로 진행하니 주변 음식점 위치가 제대로 나오네요!

      혹시 여기에 오픈API 파싱하여 구글맵에 원하는 장소 마커 뜨게하는 방법도 있을까요??
      위도와 경도 나와있는 xml형식 적용은 혹시 불가능한건가요? ㅠㅠ

    • 네비게이션 2019.10.15 02:13


      안녕하세요.
      자세하고 따라하기 쉽게 설명해주셔서 감사합니다. 항상 잘 보고있습니다.

      제가 기존에 올리신 위치띄우기 + 목적지 설정해서 거리찾기 + 이번 장소띄우기를 하려고 합니다.
      위치띄우고 장소띄우기까지는 에러없이 잘 돌아갑니다.
      하지만 목적지 설정하는 포스트를 보고 따라할 때, 기존 위치띄우기 포스트(java코드만 쭉 써있는 포스트)코드를 참고하라하셔서 새로 쓰고 여기에 위치띄우기 장소띄우기를 했더니 에러가 납니다. 목적지코드만 써도 제 위치를 잡지 못하고요..

      혹시 어느부분이 오류인것인지 봐주실 수 있을까요? 로그캣을 첨부하겠습니다.


      항상 좋은 글 감사합니다.

    • 네비게이션 2019.10.15 02:19


      Caused by: android.view.InflateException: Binary XML file line #32: Binary XML file line #32: Error inflating class fragment
      Caused by: android.view.InflateException: Binary XML file line #32: Error inflating class fragment
      Caused by: java.lang.IllegalArgumentException: Binary XML file line #32: Duplicate id 0x7f08009f, tag null, or parent id 0x7f080098 with another fragment for com.google.android.gms.maps.SupportMapFragment

      로그캣이 전부다 안올라가네요..

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.15 12:42 신고


        정확한 원인을 찾기엔 로그가 부족하네요.

        혹시 프래그먼트를 사용하나요?

        레이아웃에서 SupportMapFragment를 사용하나요?

      • 네비게이션 2019.10.17 23:27


        네 둘다 support로 사용하고있습니다.

        android.view.InflateException: Binary XML file line #32 in com.example.drive:layout/activity_main: Binary XML file line #32 in com.example.drive:layout/activity_main: Error inflating class fragment
        at android.app.Ac
        라고 뜨는데, fragment가 잘못된건가요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.18 16:44 신고


        혹시 액티비티로 작성된 예제를 프래그먼트로 바꾸었나요?

      • 네비게이션 2019.11.05 16:24


        <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_gravity="center_horizontal"
        android:paddingTop="0dp">

        <Button
        android:id="@+id/button1"
        android:layout_width="550px"
        android:layout_height="wrap_content"
        android:text="근처 카페 검색" />

        <Button
        android:id="@+id/button"
        android:layout_width="550px"
        android:layout_height="wrap_content"
        android:text="경로 안내 시작" />

        </LinearLayout>


        <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="9"
        android:name="com.google.android.gms.maps.SupportMapFragment" />

      • 네비게이션 2019.11.05 16:25


        xml은 현재 이렇게 해놨습니다

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.05 19:43 신고


        자바코드에서 레이아웃을 불러오는 부분을 확인해봐야 할듯보입니다

    • 배우로왔습니다 2019.10.16 22:56


      배달앱(상업적용도 x)을만들어야하는데 제가 만든앱에서만 등록한 음식점을 보이게할려면
      placetype을 제가 자체적으로 만들어야할까요? 사실상 이건 많이 힘들겟죠?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.17 16:06 신고


        등록한 식당만 보여줄꺼라면 Places API를 사용할 필요가 없습니다. 식당 정보와 GPS를 데이터베이스에 저장하고 현재 위치에서 일정 반경내에 있는 식당만 데이터베이스에 질의하여 결과를 지도에 마커로 보여주면 될 듯합니다.

        선택한 지역에 있는 가게를 보여주는 거라면 쉽게 구현될 듯한데

        현재 위치에서 일정 반경내에 있는 식당만 보여주려면 고민을 좀 해야 할듯합니다.

    • 프래그먼트 2019.10.23 18:23


      메인엑티비티 말구
      프래그먼트에 적용하는방법은없나요?
      프래그먼트에 현재위치까지 표시는됩니다.

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.23 18:52 신고


        구글에서 아래처럼 검색해보시면 예제들을 찾으실 수 있습니다.

        google map fragment

      • 프래그먼트 2019.10.24 10:00


        @Override
        public void onPlacesSuccess(final List<Place> places) {

        runOnUiThread(new Runnable() {
        @Override
        public void run() {
        for (noman.googleplaces.Place place : places) {

        LatLng latLng
        = new LatLng(place.getLatitude()
        , place.getLongitude());

        String markerSnippet = getCurrentAddress(latLng);

        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latLng);
        markerOptions.title(place.getName());
        markerOptions.snippet(markerSnippet);
        Marker item = map.addMarker(markerOptions);
        previous_marker.add(item);

        }

        //중복 마커 제거
        HashSet<Marker> hashSet = new HashSet<Marker>();
        hashSet.addAll(previous_marker);
        previous_marker.clear();
        previous_marker.addAll(hashSet);

        }
        });

        여기서
        runOnUiThread 이부분이랑

        String markerSnippet = getCurrentAddress(latLng);이부분을 어떤식으로 수정해야할지 모르겠습니다..

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.24 10:03 신고


        그대로 사용하면 에러가 발생하나요?

      • 프래그먼트 2019.10.24 13:05


        일단 하루정도 더 해보구 내일또
        댓글달아볼게여

    • 프래그먼트 2019.10.24 09:31


      감사합니다

    • 프래그먼트 2019.10.25 10:15


      안녕하세요..
      2틀동안 해보았지만 너무힘이들어서 도움을 요청드립니다..현재 제코드는
      package com.study.hairshop;

      import android.Manifest;
      import android.content.Context;
      import android.content.pm.PackageManager;
      import android.location.Address;
      import android.location.Geocoder;
      import android.location.Location;
      import android.location.LocationListener;
      import android.location.LocationManager;
      import android.os.Bundle;
      import android.support.annotation.Nullable;
      import android.support.v4.app.ActivityCompat;
      import android.support.v4.app.Fragment;
      import android.support.v4.content.ContextCompat;
      import android.util.Log;
      import android.view.LayoutInflater;
      import android.view.View;
      import android.view.ViewGroup;
      import android.widget.Button;
      import android.widget.ListView;
      import android.widget.Toast;

      import com.google.android.gms.maps.CameraUpdateFactory;
      import com.google.android.gms.maps.GoogleMap;
      import com.google.android.gms.maps.MapView;
      import com.google.android.gms.maps.MapsInitializer;
      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.ArrayList;
      import java.util.HashSet;
      import java.util.List;
      import java.util.Locale;

      import noman.googleplaces.NRPlaces;
      import noman.googleplaces.Place;
      import noman.googleplaces.PlaceType;
      import noman.googleplaces.PlacesException;
      import noman.googleplaces.PlacesListener;

      public class Fragment1 extends Fragment implements OnMapReadyCallback, PlacesListener {

      private static final String TAG = "lecture";


      SingerAdapter adapter;

      private MapView mapView = null;

      MarkerOptions myLocationMarker;

      GoogleMap map;

      ListView listView1;

      List<Marker> previous_marker = null;

      LatLng currentPosition;


      public Fragment1() {

      }


      @Override
      public void onCreate(@Nullable Bundle savedInstanceState) {


      super.onCreate(savedInstanceState);


      if(ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_FINE_LOCATION)
      != PackageManager.PERMISSION_GRANTED){

      if(ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
      android.Manifest.permission.ACCESS_FINE_LOCATION)){

      }else{
      ActivityCompat.requestPermissions(getActivity(),
      new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
      }
      }



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


      }


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

      final View layout = inflater.inflate(R.layout.activity_fragment1, container, false);


      adapter = new SingerAdapter(getActivity());

      SingerItem item1 = new SingerItem("매장명","010-1111-1111",R.drawable.face1);
      adapter.addItem(item1);

      ListView listView1 = (ListView) layout.findViewById(R.id.listView1);
      listView1.setAdapter(adapter);

      mapView = layout.findViewById(R.id.map);
      mapView.onCreate(savedInstanceState);
      mapView.onResume();
      mapView.getMapAsync(new OnMapReadyCallback(){
      @Override
      public void onMapReady(GoogleMap googleMap){
      Log.d(TAG,"GoogleMap is ready.");
      map = googleMap;
      requestMyLocation();

      previous_marker = new ArrayList<Marker>();

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


      }

      });



      return layout;

      }


      @Override
      public void onSaveInstanceState(Bundle outState) {
      super.onSaveInstanceState(outState);
      mapView.onSaveInstanceState(outState);
      }


      @Override
      public void onResume() {
      super.onResume();
      mapView.onResume();

      }

      @Override
      public void onPause() {
      super.onPause();
      mapView.onPause();

      }

      @Override
      public void onLowMemory() {
      super.onLowMemory();
      mapView.onLowMemory();
      }

      @Override
      public void onDestroy() {
      super.onDestroy();
      mapView.onLowMemory();

      }



      private void showMyLocationMarker(Location location){
      if(myLocationMarker == null){

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

      myLocationMarker = new MarkerOptions();
      myLocationMarker.position(new LatLng(location.getLatitude(),location.getLongitude()));
      myLocationMarker.title("***내위치***\n");
      myLocationMarker.snippet("GPS로 확인한 위치");
      myLocationMarker.icon(BitmapDescriptorFactory.fromResource(R.drawable.mylocation));
      map.addMarker(myLocationMarker);

      }else {
      myLocationMarker.position(new LatLng(location.getLatitude(),location.getLongitude()));
      }
      }


      private void requestMyLocation(){
      LocationManager manager =
      (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);

      try {
      long minTime = 10000;
      float minDistance = 0;
      manager.requestLocationUpdates(
      LocationManager.GPS_PROVIDER,
      minTime,
      minDistance,
      new LocationListener() {
      @Override
      public void onLocationChanged(Location location) {
      Log.d(TAG , location.toString());
      showCurrentLocation(location);
      }

      @Override
      public void onStatusChanged(String provider, int status, Bundle extras) {

      }

      @Override
      public void onProviderEnabled(String provider) {

      }

      @Override
      public void onProviderDisabled(String provider) {

      }
      }
      );

      Location lastLocation = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
      if(lastLocation != null){
      showCurrentLocation(lastLocation);
      }

      manager.requestLocationUpdates(
      LocationManager.NETWORK_PROVIDER,
      minTime,
      minDistance,
      new LocationListener() {
      @Override
      public void onLocationChanged(Location location) {
      showCurrentLocation(location);
      }

      @Override
      public void onStatusChanged(String provider, int status, Bundle extras) {

      }

      @Override
      public void onProviderEnabled(String provider) {

      }

      @Override
      public void onProviderDisabled(String provider) {

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

      private void showCurrentLocation(Location location){
      LatLng curPoint = new LatLng(location.getLatitude(),location.getLongitude());

      //map.animateCamera(CameraUpdateFactory.newLatLngZoom(curPoint,15));
      map.moveCamera(CameraUpdateFactory.newLatLngZoom(curPoint,15));

      showMyLocationMarker(location);
      }

      @Override
      public void onMapReady(GoogleMap googleMap) {



      }


      @Override
      public void onPlacesFailure(PlacesException e) {

      }

      @Override
      public void onPlacesStart() {

      }

      @Override
      public void onPlacesSuccess(final List<Place> places) {


      Log.d(TAG,"진행중");

      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      for (noman.googleplaces.Place place : places) {

      LatLng latLng
      = new LatLng(place.getLatitude()
      , place.getLongitude());

      String markerSnippet = getCurrentAddress(latLng);

      MarkerOptions markerOptions = new MarkerOptions();
      markerOptions.position(latLng);
      markerOptions.title(place.getName());
      markerOptions.snippet(markerSnippet);
      Marker item = map.addMarker(markerOptions);
      previous_marker.add(item);




      }

      //중복 마커 제거
      HashSet<Marker> hashSet = new HashSet<Marker>();
      hashSet.addAll(previous_marker);
      previous_marker.clear();
      previous_marker.addAll(hashSet);

      }


      });




      }

      private void runOnUiThread(Runnable runnable) {



      }

      @Override
      public void onPlacesFinished() {

      }

      public String getCurrentAddress(LatLng latlng) {

      //지오코더... GPS를 주소로 변환
      Geocoder geocoder = new Geocoder(getActivity(), Locale.getDefault());

      List<Address> addresses;

      try {

      addresses = geocoder.getFromLocation(
      latlng.latitude,
      latlng.longitude,
      1);
      } catch (IOException ioException) {
      //네트워크 문제
      Toast.makeText(getActivity(), "지오코더 서비스 사용불가", Toast.LENGTH_LONG).show();
      return "지오코더 서비스 사용불가";
      } catch (IllegalArgumentException illegalArgumentException) {
      Toast.makeText(getActivity(), "잘못된 GPS 좌표", Toast.LENGTH_LONG).show();
      return "잘못된 GPS 좌표";

      }


      if (addresses == null || addresses.size() == 0) {
      Toast.makeText(getActivity(), "주소 미발견", Toast.LENGTH_LONG).show();
      return "주소 미발견";

      } else {
      Address address = addresses.get(0);
      return address.getAddressLine(0).toString();
      }



      }

      public void showPlaceInformation(LatLng location)
      {
      map.clear();//지도 클리어

      if (previous_marker != null)
      previous_marker.clear();//지역정보 마커 클리어

      new NRPlaces.Builder()
      .listener(Fragment1.this)
      .key("저의키입니다.")
      .latlng(location.latitude, location.longitude)//현재 위치
      .radius(500) //500 미터 내에서 검색
      .type(PlaceType.BOOK_STORE) //음식점
      .build()
      .execute();
      }


      }
      이런식으로 프래그먼트에 구현해두었고
      현재위치에 마커까지 표시되는 상태입니다. 버튼클릭시에 주변정보가 뜨게만들고싶은데
      버튼클릭하면 화면변화는없고
      E/Places: https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=저의키입니다.&location=37.4786188,126.8788804&radius=500&type=book_store
      I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
      (HTTPLog)-Static: isSBSettingEnabled false
      E/Places: noman.googleplaces.PlacesException: OVER_QUERY_LIMIT
      E/Places: noman.googleplaces.PlacesException: OVER_QUERY_LIMIT

      라는에러가 뜹니다. 어느부분이 문제인지 도저히 모르겠어서 도움요청드립니다...

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.25 10:58 신고


        OVER_QUERY_LIMIT 에러메시지상으론 무료로 사용할 수있는 하루 Place API 사용량을 초과한 것으로 보입니다.

      • 프래그먼트 2019.10.25 11:04


        사용량 초과전에 주변정보를
        불러오는건확인하였는데
        그 주변정보가 지도상에 아무런표시가되지않습니다..API사용량 에러이전에
        코딩에 문제가있는거같은데
        개발초보자다보니..코드상에러가없어서
        어느부분이 문제인지 잘모르겠습니다;;ㅜㅜ

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.25 17:23 신고


        onPlacesSuccess 메소드에서 주변 정보를 지도에 마커형태로 추가합니다.

        주변 정보를 가져오기위해 REST API를 사용하다보니 호출후 어느정도 시간이 지나야 결과를 화면에 보여줄 수 있습니다.

      • 프래그먼트 2019.10.25 17:32


        넵 아직완성은못했지만
        될떄까지 해보겟습니다 감사합니다

    • 2019.11.02 17:17


      비밀댓글입니다

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.03 08:59 신고



        첫번째는 확인이 필요할듯합니다.

        두번째는 아래 링크를 참고해보세요.
        https://hashcode.co.kr/questions/6462/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EB%B0%B0%ED%8F%AC%EC%8B%9C-%EA%B5%AC%EA%B8%80%EB%A7%B5%EC%9D%B4-%EB%9C%A8%EC%A7%80%EC%95%8A%EB%8A%94-%ED%98%84%EC%83%81

    • . 2019.11.15 00:16


      식당 place를 구현하는 NRPlace와 Bar place를 구현하는 NRPlace를 따로 만들어서 각 place를 다른 색깔의 marker로 띄우려고 하는데, NRPlace.Builder()에 따른 메소드를 여러개 만들 수도 있나요..?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.15 09:41 신고


        해보지는 않았는데.. 가능할 듯합니다.

      • . 2019.11.17 23:36


        NRPlace를 객체로 선언해서 두개를 만들어보려고 했는데 자꾸 오류가 뜨네요ㅠㅠ 혹시 NRPlace를 어떻게 쓰는지 좀 더 조언을 주실 수 있을까요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.18 09:02 신고


        NRPlace를 두개 사용이 안된다면

        조건에 따라 아래에 지정하는 타입을 바꾸어보는게 어떨까 싶네요..

        .type(PlaceType.RESTAURANT) //음식점

      • . 2019.11.18 14:36


        감사합니다!
        혹시 NRPlace의 opennow 변수가 true일 때와 flase일 때를 불러오고 싶으면 어떻게 선언하면 될까요?ㅠㅠ

        placetype은 이런식으로 불러올 수 있는 것 같던데
        if(place.getTypes().equals(PlaceType.RESTAURANT)) { }

        opennow는 NRPlace.Builder().opennow(true)
        이런 식으로밖에 안 뜨더라구요ㅠㅠ
        opennow 값에 따라 다른 옵션을 주고 싶은데,, NRPlace는 검색해도 사용방법이 자세히 안나와서 질문드립니다ㅜㅜ

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.18 19:41 신고


        타입만 바꾼 장소찾는 코드를 2개 작성해서 전역 변수값에따라 원하는 걸 실행하도록 해보세요

    • 케익 2019.11.15 22:43


      하나하나 따라하면서 정말 많이 배웠습니다. 자세한 설명 감사합니다. 그런데 이걸 백그라운드에서도 계속 현재위치를 받으려면 어떤식으로 만들어야하나요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.16 17:57 신고


        액티비티를 서비스로 바꿔야.할듯합니다.

      • 케익 2019.11.16 20:34


        서비스로 바꿔서 여러번 시도해봤는데 계속 안돼서요. 대충 어떤 식으로 해야하는지 알려주실 수 있으신가요? 지금 이 상태에서는 많이 수정을 해야하나요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.16 21:49 신고


        다음 링크를 참고해보세요..
        https://github.com/BlackBlind567/Location_Updates-Background_Foreground/blob/master/app/src/main/java/com/atomsindia/local/LocationUpdatesService.java

      • 케익 2019.11.17 04:23


        정말 감사합니다. 알려주신거 참고해서 만들었네요. 복 받으세요 ㅎㅎ

    • 122 2019.11.16 23:27


      잘나옵니다 저는 음식점이아닌 병원중에서도 피부과병원을 띄우게 만드려고 하는데 RESTAURANT 대신에 뭐를 넣어야 하나요?? 없는거 같은데 ㅜㅜ 이럴떄는 어떻게 하죠 ㅜㅜ 도와주세요

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.17 16:56 신고


        HOSPITAL를 사용하고 검색 결과에서 피부과 여부를 확인해볼 수 밖에 없습니다.

      • 122 2019.11.17 20:23


        하는방법이 어떻게 될까요 ?? 피부과라는 단어를 포함시키도록 해야할거 같은데..

        public void showPlaceInformation(LatLng location)
        {
        mMap.clear();//지도 클리어

        if (previous_marker != null)
        previous_marker.clear();//지역정보 마커 클리어

        new NRPlaces.Builder()
        .listener(MainActivity.this)
        .key("AIzaSyDLk2Np5n9_@@@@@@@@@@@")
        .latlng(location.latitude, location.longitude)//현재 위치
        .radius(500) //500 미터 내에서 검색
        .type(PlaceType.HOSPITAL)
        .build()
        .execute();
        }

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.17 20:37 신고


        onPlacesSuccess 함수에서 다음 처럼 장소 이름을 가져와 마커 이름으로 사용하고 있습니다.

        markerOptions.title(place.getName());


        place.getName()로 가져오는 이름에 피부과가 포함되었는지 체크하여 피부과만 보여주면 될듯합니다.


        하지만
        피부과라는 이름이 포함되지 않은 피부과 병원은 검색할 수 없습니다.


        꼭 피부과 병원만 검색해야 한다면 다른 공개된 데이터베이스가 있는지 찾아보셔야 할듯합니다.

      • 122 2019.11.17 20:48


        public void onPlacesSuccess(final List<Place> places) {

        runOnUiThread(new Runnable() {
        @Override
        public void run() {
        for (noman.googleplaces.Place place : places) {

        LatLng latLng
        = new LatLng(place.getLatitude()
        , place.getLongitude());

        String markerSnippet = getCurrentAddress(latLng);

        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latLng);
        if(place.getName().equals("피부과")) {
        markerOptions.title(place.getName());
        }
        markerOptions.snippet(markerSnippet);
        Marker item = mMap.addMarker(markerOptions);
        previous_marker.add(item);

        }

        이렇게 하면되나요?? 피부과 이름이 포함된 병원만 띄우면 됩니다 ㅜㅜ 이것만 해결하면 됩니다 ㅜㅜ..

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.17 22:42 신고


        다음처럼 하면 되지 않을까 싶네요

        for (noman.googleplaces.Place place : places) {

        String name = place.getName();

        if(name.contains("피부과")){

        LatLng latLng
        = new LatLng(place.getLatitude()
        , place.getLongitude());

        String markerSnippet = getCurrentAddress(latLng);

        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latLng);
        markerOptions.title(place.getName());
        markerOptions.snippet(markerSnippet);
        Marker item = mMap.addMarker(markerOptions);
        previous_marker.add(item);

        }
        }

      • 122 2019.11.17 23:06


        잘 되긴 하는데 이게.. radius를 10000으로나 높혀봐도 하나도 안뜨네요 ㅜㅜ 근방 10km내에 피부과가 하나도 없을리가 없는데 근데 집앞에 연세병원이 하나 있는데 contain("연세")하면 딱 거기 하나만 뜨는거 보니까 코드상 오류는 없는거 같은데 사용된 구글api가 정보가 빈약한 건가요?? 누락된 병원들도 많네요

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.18 09:00 신고


        구글 API에서 모든 병원 위치를 제공할 것 같지는 않습니다.

      • BlogIcon 122 2019.11.18 20:52


        결과가 딱 하나 나오네요 어느정도 정보를 띄우려면 뭘 해야하나요?? 공공데이터포털이라는 사이트에서 api를 개인적으로 받을수 있다던데 그 api를 갖다써도 되는건가요? 또한 구글api와 중복 적용이 되나요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.18 21:32 신고


        같이 써도 되지만 효율적으로 관리하려면 하나만 사용하는게 좋을듯합니다.

        마커 정보 입력시 따로 가져온 정보를 추가하여 보여주면 되기때문에 구글에서 제공안한 정보를 사용해도 무방합니다.

    • 122 2019.11.18 22:42


      혹시 써본적 있으신가요? Api만 그대로 바꿔 복붙하면 끝인가요??

    • 니니 2019.11.19 10:22


      장소검색 없이 앱에 들어가자마자 특정장소가 뜨게 하려면 button 부분만 삭제하면 될까요??

    • asdkhj7162 2019.11.21 16:16


      안녕하세요! 너무 많은것을 보고 배워갑니다.
      질문이 하나 있는데, 현재 작성하신 프로젝트를 보고 배우면서, 지식을 습득하고 있는 과정중인데
      현재 진행하신 프로젝트에서 placetype이 음식점인 마커들을 클릭하다 보면 제 현재 위치가 계속 Refresh가 되면서 앱 화면의 포커스가 현재 위치 마커로 계속 맞춰지는데, 이 현상은 setCurrentLocation 메소드 쪽에서 발생하는 건가요? 항상 많은것을 배워갑니다. 감사합니다!

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.21 22:03 신고


        맞습니다.

        setCurrentLocation 함수를 호출하여 현재위치가 지도 중심이 되도록 합니다.

      • asdkhj7162 2019.11.22 01:08


        마커를 눌러본다던가 하면서 맵의 이곳저곳을 왔다갔다 하고 있는데, 강제적으로 현재 위치로 계속 이동하는 것은 어떤 부분에서 일어나는 문제점 일까요? 혹시 참고할만한 구분 말씀해주시면 너무 감사하겠습니다.

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.22 08:36 신고


        다음 포스트에 있는

        Android Google Map에 현재 위치 표시하기( FusedLocationProviderClient 사용)

        https://webnautes.tistory.com/1249



        setCurrentLocation 함수의 다음 부분이 카메라를 현재 위치로 이동시키는 부분입니다.

        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(currentLatLng);
        mMap.moveCamera(cameraUpdate);

      • asdkhj7162 2019.11.22 09:53


        감사합니다. 참고해서 잡아보겠습니다.

Designed by Tistory.