ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Google Maps Android API 사용 방법 및 예제
    Android/Google Map 2019. 8. 15. 10:22




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





    1. 간단한 안드로이드 구글맵 예제 동작시키기


    2. Google Maps Android API 예제 코드 설명


    3. Google Maps Android API를 사용할 때 발생할 수 있는 문제와 해결방법


    4. 관련 포스팅


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

        4.2. Android Google Map에 현재 위치 표시하기( GoogleApiClient, FusedLocationApi 사용)

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

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




    테스트 환경은 다음과 같습니다.


    Android Studio 3.4.2

    Android 9.+ ( API 29 )




    2015.02.10

    . . . . . . . . .

    2019. 5. 6   로그캣에서 에러 확인하는 법과 에뮬레이터에서 실행시 문제점  추가 

    2019. 7. 19  androidx 관련 내용 추가 

    2019. 8. 15  SupportMapFragment로 변경 




    1. 간단한 안드로이드 구글맵 예제 동작시키기

    먼저 구글맵 예제를 실행시켜 보고,  후반부에 예제 코드를 설명합니다. 



    1. Google Developers Console 사이트 (https://console.developers.google.com/apis/dashboard )에 접속하여 프로젝트 만들기를 클릭합니다.


    자주 구성이 바뀌는 편이어서 포스팅에서 진행한 캡쳐 화면과 차이가 있을 수 있습니다.





    2. 적당한 프로젝트 이름을 적고 만들기를 클릭합니다.





    3.  잠시 기다리면 새로운 프로젝트 생성이 완료 됩니다. 


    Google Maps Android API를 사용하려면 추가 설정이 필요합니다.  API 및 사용 서비스 사용 설정을 클릭합니다.





    4. google maps android를 검색하여 Maps SDK for Android를 선택합니다. 





    5. 사용 설정을 클릭합니다.





    6. API가 활성화 되었습니다. 인증 설정을 하기 위해 사용자 인증 정보를 클릭합니다. 





    7. 사용자 인증 정보 만들기를 클릭하여 보이는 메뉴에서 API 키를 클릭합니다. 





    8.   키 제한을 클릭합니다. 





    9.  앞에서 생성된 API 키에 사용 제한을 둘 수 있는 웹페이지가 보입니다.

    애플리케이션 제한사항, API 제한사항을 설정할 수 있습니다.





    10. Android 앱을 선택하고 항목  추가를 클릭합니다.





    11. Google Maps Android API를 사용할 안드로이드 프로젝트의 패키지 이름과 Android Studio가 설치된 컴퓨터에서 생성된 SHA-1 인증서 지문이 필요합니다.


     



    12.  SHA-1 인증서 지문을 얻기 위한 과정부터 진행합니다.  윈도우키 + R을 누른 후 cmd를 입력하고 엔터를 눌러서 명령 프롬프트 창을 엽니다. 





    윈도우에서는  다음 명령으로 SHA-1 인증서 지문을 획득할 수 있습니다.


    "C:\Program Files\Android\Android Studio\jre\bin\keytool" -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android




    참고로 우분투 리눅스에서는 다음 명령을 사용합니다.


    keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android




    SHA1 옆에 있는 문자열을 복사해 놓으면 됩니다. 





    문제 없으면 14번을 진행하고, 그렇지 않으면 13번을 확인해보세요..




    13.  안드로이드 스튜디오에서 앱을 빌드하여 안드로이드 디바이스에 설치한 적이 없어서 다음과 같은 에러가 발생합니다.


    keytool 오류: java.lang.Exception: 저장소 파일이 존재하지 않음: C:\Users\webnautes\.android\debug.keystore



    간단한 안드로이드 프로젝트를 생성하여 빌드 후, 안드로이드 디바이스에 설치하면 debug.keystore 파일이 사용자 디렉토리의 하위 디렉토리인 .android 디렉토리 안에 생성됩니다.


    다시 12번을 진행해보면  SHA1 fingerprint 획득할 수 있습니다.




    14.  Google Maps Android API를 사용할 안드로이드 프로젝트를 준비해놓았다면 패키지 이름을 따로 복사해놓고 15번을 진행합니다.  


    그렇지 않다면 안드로이드 스튜디오를 실행하여 새로운 프로젝트를 생성합니다.  



    메뉴에서 File > New > New Project를 선택합니다.

    Create New Project 창의 Choose your project에서 Empty Activity를 선택합니다.





    Configure your project의 Name항목에 프로젝트 이름을 적어줍니다.





    안드로이드 프로젝트 생성이 완료되면 MainActivity.java 파일에서 패키지 이름을 복사해둡니다.





    15. Google Developers Console 사이트에  복사해두었던 패키지 이름SHA-1 인증서 지문을 붙여넣기하고 완료를 클릭합니다.  





    16. API 제한사항에서  키 제한을 선택하고 콤보박스에서 Maps SDK for Android를 체크합니다.  이제 저장을 클릭합니다.





    17.  API 키를 복사해둡니다.





    18. 매네페스트 파일 AndroidManifest.xml<application> 태그 하위요소로 <meta-data> 태그를 사용하여 17번에서 복사해둔 API키를 입력해줍니다.



        <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">

            <meta-data
                android:name="com.google.android.geo.API_KEY"
                android:value="API키" />
           
            <activity android:name=".MainActivity">




    19. 등록 받은 키 확인이 필요하다면 Google Developers Console 사이트 (https://console.developers.google.com/apis/dashboard )에서 왼쪽 상단에 있는 프로젝트명을 Google Maps Android API를 위한 것으로 바꾸어 선택합니다.

    생성한 프로젝트가 하나라면 자동으로 선택됩니다.





    왼쪽에 보이는 메뉴에서 사용자 인증 정보를 클릭합니다.




     API 키를 확인할 수 있습니다.



         


    20.  Google Maps Android API를 사용하려면 Google Play services 라이브러리 패키지를 설치해줘야 합니다.


    안드로이드 스튜디오로 돌아와서 메뉴에서 Tools > SDK Manager를 선택합니다. 

    SDK Tools 탭을 클릭하고 Google Play services 항목을 체크하고 Apply를 클릭하여 설치를 진행합니다.

     




    21.  모듈 app build.gradleGoogle Play Services 라이브러리를 프로젝트에서 사용한다고 추가해줘야 합니다.



    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'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'androidx.test:runner:1.2.0'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    }



    추가해 준 후 , Sync Now를 클릭합니다. 



     

    24. 레이아웃 파일 activity_main.xml 을 다음 내용으로 바꾸어 줍니다.  <fragment> 태그를 지도가 표시될 위치에 적어줍니다.



    <?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"
        tools:context=".MainActivity" >

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


    </LinearLayout>



     

    25. 자바 코드 파일 MainActivity.java 를 다음 내용으로 대체합니다. 



    import androidx.appcompat.app.AppCompatActivity;
    import android.os.Bundle;
    import com.google.android.gms.maps.CameraUpdateFactory;
    import com.google.android.gms.maps.GoogleMap;
    import com.google.android.gms.maps.OnMapReadyCallback;
    import com.google.android.gms.maps.SupportMapFragment;
    import com.google.android.gms.maps.model.LatLng;
    import com.google.android.gms.maps.model.MarkerOptions;



    public class MainActivity extends AppCompatActivity
            implements OnMapReadyCallback {

        private GoogleMap mMap;


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

            SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.map);
            mapFragment.getMapAsync(this);
        }

        @Override
        public void onMapReady(final GoogleMap googleMap) {

            mMap = googleMap;

            LatLng SEOUL = new LatLng(37.56, 126.97);

            MarkerOptions markerOptions = new MarkerOptions();
            markerOptions.position(SEOUL);
            markerOptions.title("서울");
            markerOptions.snippet("한국의 수도");
            mMap.addMarker(markerOptions);

            mMap.moveCamera(CameraUpdateFactory.newLatLng(SEOUL));
            mMap.animateCamera(CameraUpdateFactory.zoomTo(10));
        }

    }




    26.  Android Studio 3.3으로 업데이트후 다음과 같은 에러가 발생했습니다.

    Android Studio 3.4에서는 에러가 나지 않습니다.  같은 에러가 나는 경우에만 해주세요.


    E/AndroidRuntime: FATAL EXCEPTION: Thread-6
        Process: com.tistory.webnautes.googlemapsandroidapiexample, PID: 7919
        java.lang.NoClassDefFoundError: Failed resolution of: Lorg/apache/http/ProtocolVersion;
            at ez.b(:com.google.android.gms.dynamite_mapsdynamite@14799088@14.7.99 (100800-223214910):3)
            at ey.a(:com.google.android.gms.dynamite_mapsdynamite@14799088@14.7.99 (100800-223214910):3)
            at fa.a(:com.google.android.gms.dynamite_mapsdynamite@14799088@14.7.99 (100800-223214910):15)
            at com.google.maps.api.android.lib6.drd.al.a(:com.google.android.gms.dynamite_mapsdynamite@14799088@14.7.99 (100800-223214910):6)
            at ed.a(:com.google.android.gms.dynamite_mapsdynamite@14799088@14.7.99 (100800-223214910):21)
            at ed.run(:com.google.android.gms.dynamite_mapsdynamite@14799088@14.7.99 (100800-223214910):8)
        Caused by: java.lang.ClassNotFoundException: Didn't find class "org.apache.http.ProtocolVersion" on path: DexPathList[[zip file "/data/user_de/0/com.google.android.gms/app_chimera/m/0000000d/MapsDynamite.apk"],nativeLibraryDirectories=[/data/user_de/0/com.google.android.gms/app_chimera/m/0000000d/MapsDynamite.apk!/lib/x86_64, /system/lib64]]




    매네페스트 파일 AndroidManifest.xml의 <application> 태그 하위요소로 다음 한줄을 추가해주면 해결됩니다.


    <uses-library android:name="org.apache.http.legacy" android:required="false"/>


        <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">

            <uses-library android:name="org.apache.http.legacy" android:required="false"/>

            <meta-data
                android:name="com.google.android.geo.API_KEY"




    27. 실행 결과 화면입니다. 서울 중앙에 빨간색 마커가 보이고 클릭하면 마커에 추가해두었던 설명이 보입니다.

      

       




    2. Google Maps Android API 예제 코드 설명

    1. MapFragment는 앱에 지도를 표시하기 위해 사용되는 컴포넌트로 관련 처리를 자동으로 해줍니다. 앱에서 사용하기 위해서는 레이아웃의 액티비티에 <fragment> 태그를 사용하여 추가시켜 주어야 합니다.


    <?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"
        tools:context=".MainActivity" >

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


    </LinearLayout>




    2. MainActivity 클래스에서  OnMapReadyCallback 인터페이스를 구현한다고 선언해놓고


    public class MainActivity extends AppCompatActivity
            implements OnMapReadyCallback {




    OnMapReadyCallback 인터페이스의 onMapReady 메소드를 구현해줘야 합니다.  

    맵이 사용할 준비가 되었을 때(NULL이 아닌 GoogleMap 객체를 파라미터로 제공해 줄 수 있을 때)  호출되어지는 메소드입니다.  



        @Override
        public void onMapReady(final GoogleMap map) {

          . . . . . . . . . . . . . . . . . . . .

        }




    MarkerOptions으로 마커가 표시될 위치(position), 마커에 표시될 타이틀(title), 마커 클릭시 보여주는 간단한 설명(snippet)를 설정하고 addMarker 메소드로 GoogleMap 객체에 추가해주면 지도에 표시됩니다.


            LatLng SEOUL = new LatLng(37.56, 126.97);

            MarkerOptions markerOptions = new MarkerOptions();
            markerOptions.position(SEOUL);
            markerOptions.title("서울");
            markerOptions.snippet("한국의 수도");
            mMap.addMarker(markerOptions);




    moveCamera 메소드를 사용하여 카메라를 지정한 경도, 위도로 이동합니다. 

    CameraUpdateFactory.zoomTo 메소드를 사용하여 지정한 단계로 카메라 줌을 조정합니다.  1 단계로 지정하면 세계지도 수준으로 보이고 숫자가 커질수록 상세지도가 보입니다. 


            mMap.moveCamera(CameraUpdateFactory.newLatLng(SEOUL));
            mMap.animateCamera(CameraUpdateFactory.zoomTo(10));




    3. 이제 onCreate 메소드에서 getMapAsync() 메소드를 호출하여 GoogleMap 객체가 준비될 때 실행될 콜백을 등록합니다. 


    그러기 위해서는 레이아웃에 추가했던 프래그먼트(com.google.android.gms.maps.SupportMapFragment)의 핸들을 가져와야 합니다. 

    FragmentManager.findFragmentById 메소드를 사용하여 지정한 ID를 갖는 프래그먼트의 핸들을 가져옵니다. 


    getMapAsync() 메소드가 메인 쓰레드에서 호출되어야 메인스레드에서 onMapReady 콜백이 실행됩니다.


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

            SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.map);
            mapFragment.getMapAsync(this);
        }




    3. Google Maps Android API를 사용할 때 발생할 수 있는 문제와 해결방법

    구글 지도가 안보이는 원인을 파악하려면 안드로이드 스튜디오 하단에 있는 로그캣(logcat)에서 관련 메시지를 확인해야 합니다. 


    다음처럼 Verbose 오른쪽에 있는 창에 google을 입력하고.. 구글맵 예제 앱을 실행해보면 구글맵 관련 메시지를 쉽게 찾을 수 있습니다. 


     




    1. 처음 안드로이드 폰에 설치되면서 실행되면 흰화면이 나온 상태에서 좀 시간이 걸리고 나서 구글맵이 보이고 그 다음 실행부턴 정상적으로 되는 증상이 있으면 다음 포스팅을 참고하세요.

    Android Studio 2.3.1에서는 해결되었습니다.


    Android Studio 2.x 버전에서 Google Map 로딩이 늦는 문제 해결 -> Instant Run 해제

    http://webnautes.tistory.com/1056 




    2. 킷캣(안드로이드 4.4) 이하 버전 사용시 발생하는 문제는 다음 포스팅을 참고하세요.. 안드로이드 4.4 이상에서 발생할 수도 있습니다.


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

    http://webnautes.tistory.com/1123 




    3. 아래 화면처럼 지도가 안보이고 Google 이라는 문자만 보이면 인증 오류일 가능성이 높습니다.  


    간단한 안드로이드 구글맵 예제 동작시키기15번에서 안드로이드 프로젝트의 패키지 이름과  Android Studio가 설치된 컴퓨터에서 생성된 SHA-1 인증서 지문이 제대로 입력되었는지 확인하세요.





    로그캣에서 다음과 같은 메시지를 확인 할 수 있습니다.


    2019-05-06 20:34:07.783 9692-11591/com.tistory.webnautes.googlemapsandroidapiexample E/Google Maps Android API: Authorization failure.  Please see https://developers.google.com/maps/documentation/android-api/start for how to correctly set up the map.

    2019-05-06 20:34:07.785 9692-11591/com.tistory.webnautes.googlemapsandroidapiexample E/Google Maps Android API: In the Google Developer Console (https://console.developers.google.com)

        Ensure that the "Google Maps Android API v2" is enabled.

        Ensure that the following Android Key exists:

         API Key: 구글맵을 위해 사용중인 API 키

         Android Application (<cert_fingerprint>;<package_name>): SHA1;com.tistory.webnautes.googlemapsandroidapiexample




    4. 안드로이드 스튜디오의 에뮬레이터에서 실행하는 경우 다음 같은 메시지를 보여주며 실행이 안될 수 있습니다.

    가상 디바이스의 구글 플레이 서비스 버전이 낮아서 구글맵을 사용할 수 없다는 에러입니다. 



    로그캣에서는 다음과 같은 메시지가 보입니다. 


    2019-05-06 20:27:15.900 9692-9692/com.tistory.webnautes.googlemapsandroidapiexample W/GooglePlayServicesUtil: Google Play services out of date.  Requires 13400000 but found 11743470




    해결하려면 구글 플레이 서비스를 최신 버전으로 업데이트 해야 합니다.  업데이트를 선택합니다. 





    구글 플레이 스토어에 접속해야 하므로 구글 계정으로 로그인해야 합니다. 

     




    로그인 완료후.. 다음처럼 구글 플레이 서비스에서  업데이트 버튼이 보입니다. 선택합니다






    다음처럼 업데이트 완료 후…



    구글맵 예제를 다시 실행시켜보면 정상적으로 지도가 보입니다. 




    4. 관련 포스팅

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


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

    https://webnautes.tistory.com/1249 


    FusedLocationProviderClient는 Deprecated된 FusedLocationApi를 대체하게 되며 Google Play services 11.6.0 이상에서 사용하는 것을 권장하고 있습니다.




    4.2. Android Google Map에 현재 위치 표시하기( GoogleApiClient, FusedLocationApi 사용)


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

    https://webnautes.tistory.com/1011 




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


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

    https://webnautes.tistory.com/1080 




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


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

    https://webnautes.tistory.com/1064 





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

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

    유튜브 구독하기


    댓글 320

    • 이전 댓글 더보기
    • hy 2019.05.18 13:06


      설명 진짜 최고십니다.....유튜브 구독하러 갈게용

    • TEster 2019.05.21 20:55


      처음 만져보는데 설명이 자세하셔서 도움이 많이 되네요.

      여기 있는걸 응용해서 제가 한 번 마커를 여러개 생성하려고하니 스튜디오 자체 가상머신에서 앱이 오류가 생기네요.

      혹시 배열같은 것을 이용해서 한꺼번에 모아줘야하는지 어떻게해야 복수의 마커를 한번에 표시할 수 있는지 궁금합니다.

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.05.21 21:08 신고


        위치만 바꾸어서 다음 코드를 여러번 수행하면
        여러 개의 마커를 지도에 표시할 수 있습니다.

        LatLng SEOUL = new LatLng(37.56, 126.97);

        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(SEOUL);
        markerOptions.title("서울");
        markerOptions.snippet("한국의 수도");
        map.addMarker(markerOptions);



        현재 구글맵 API에서는 지도에 추가한 마커를 따로 저장하는 자료구조가 없는듯합니다.
        그래서 다음과 같은 방식으로 따로 리스트에 저장해줘야 합니다.


        // 마커를 저장할 리스트를 생성한 후..
        List<Marker> previous_marker = new ArrayList<Marker>();


        // 지도에 마커를 추가하면
        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latLng);
        markerOptions.title(place.getName());
        markerOptions.snippet(markerSnippet);
        Marker item = mGoogleMap.addMarker(markerOptions);


        //리스트에도 추가한 마커를 저장합니다.
        previous_marker.add(item);

    • TEster 2019.05.21 20:58


      죄송합니다. 오류로 연속 클릭하다가 댓글이 잔뜩달렸어요

      비번을 대충 치고 올려서 지금 삭제하려니 비번이 안 맞네요. 이상한 짓해서 죄송합니다 ㅠㅠ

    • TEster 2019.05.21 21:18


      일단 앞서 얘기하신대로 처음 시도해본 것은 이것입니다

      LatLng Museum = new LatLng(36.783564, 127.223225);
      MarkerOptions markerOptions = new MarkerOptions();
      markerOptions.position(Museum);
      markerOptions.title("독립기념관");
      markerOptions.snippet("겨레의 집");
      map.addMarker(markerOptions);

      LatLng Sec1 = new LatLng(36.783323, 127.221605);
      MarkerOptions markerOptions1 = new MarkerOptions();
      markerOptions.position(Sec1);
      markerOptions.title("제1전시관");
      markerOptions.snippet("겨레의뿌리");
      map.addMarker(markerOptions1);

      LatLng Sec2 = new LatLng(36.783710, 127.221090);
      MarkerOptions markerOptions2 = new MarkerOptions();
      markerOptions.position(Sec2);
      markerOptions.title("제2전시관");
      markerOptions.snippet("겨레의시련");
      map.addMarker(markerOptions2);

      LatLng Sec3 = new LatLng(36.784381, 127.220875);
      MarkerOptions markerOptions3 = new MarkerOptions();
      markerOptions.position(Sec3);
      markerOptions.title("제3전시관");
      markerOptions.snippet("나라지키기");
      map.addMarker(markerOptions3);

      LatLng Sec4 = new LatLng(36.784888, 127.220961);
      MarkerOptions markerOptions4 = new MarkerOptions();
      markerOptions.position(Sec4);
      markerOptions.title("제4전시관");
      markerOptions.snippet("겨레의함성");
      map.addMarker(markerOptions4);

      LatLng Sec5 = new LatLng(36.785034, 127.221573);
      MarkerOptions markerOptions5 = new MarkerOptions();
      markerOptions.position(Sec5);
      markerOptions.title("제5전시관");
      markerOptions.snippet("나라되찾기");
      map.addMarker(markerOptions5);

      LatLng Sec6 = new LatLng(36.784982, 127.222463);
      MarkerOptions markerOptions6 = new MarkerOptions();
      markerOptions.position(Sec6);
      markerOptions.title("제6전시관");
      markerOptions.snippet("새나라세우기");
      map.addMarker(markerOptions6);

      LatLng Sec7 = new LatLng(36.784630, 127.223815);
      MarkerOptions markerOptions7 = new MarkerOptions();
      markerOptions.position(Sec7);
      markerOptions.title("제7전시관");
      markerOptions.snippet("함께하는독립운동");
      map.addMarker(markerOptions7);

      LatLng Sec8 = new LatLng(36.784939, 127.223354);
      MarkerOptions markerOptions8 = new MarkerOptions();
      markerOptions.position(Sec8);
      markerOptions.title("입체영상관");
      markerOptions.snippet("");
      map.addMarker(markerOptions8);

      map.moveCamera(CameraUpdateFactory.newLatLng(Museum));
      map.animateCamera(CameraUpdateFactory.zoomTo(15));

      Seoul때 처럼 같은 코드를 여러번 반복하고 marker add만 한 것인데 최초 Museum만 했을때는 실행에 문제가 없었고 위처럼 코드 반복시 앱이 정지되어 버리네요.
      밑의 리스트를 쓰는것이 나을까요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.05.21 22:04 신고


        메인 쓰레드에서 많은 작업을 해서 발생한 작업 같습니다..

        다음 쓰레드내부에 마커 추가하는 것을 넣어서 해보세요..

        runOnUiThread(new Runnable() {

        @Override
        public void run() {


        }

        });

    • TEster 2019.05.21 22:25


      API 사용자체가 이버번에 처음입니다.
      죄송하지만 그렇다면

      runOnUiThread(new Runnable() {

      @Override
      public void run() {


      }

      });

      을 public class MainActivity extends AppCompatActivity implements OnMapReadyCallback 내부에 작성 후 안에
      map.moveCamera(CameraUpdateFactory.newLatLng(Museum));
      map.animateCamera(CameraUpdateFactory.zoomTo(15));

      까지 전부 옮겨 넣고 public void onMapReady ( final GoogleMap map)에는 run()만 추가하면 되는건가요?

    • TEster 2019.05.21 22:45


      도움 감사드립니다.

      좀 더 이것저것 만져봐야겠네요. 좋은 밤 되세요

    • 상훈 2019.05.29 06:07


      정말 큰 도움이 되었습니다. 많은 것을 배워갑니다. 진심으로 감사드립니다.

    • kimminsu 2019.06.05 21:06


      실행을 해보면 google play 서비스를 사용하는데 문제가있습니다. 다시 시도하세요가
      나오는데 어떤문제일까요?ㅠㅠ

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.06.05 22:47 신고


        에뮬레이터 혹은 스마트폰 중 어느 쪽에서 실행했나요?

        어느쪽이든 간에 플레이스토어에.접속이 가능한 상태인가요?

      • kimminsu 2019.06.05 23:55


        에뮬레이터로 구글 플레이스토어되는것을 생성해서 해보았는데 아예 실행이 안되어서 현재 스마트폰으로 하고있는중입니다 ㅜㅜ 에물 생성후 실행이 왜 안될까요..?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.06.06 12:11 신고


        안되는 원인은 로그캣에서 찾아봐야 합니다.. google 로 로그를 필터링하면 찾을 수 있을 듯합니다.


    • thx 2019.06.08 20:23


      상세하고 알기쉬운 설명 감사드립니다^^

      빌드는 잘되었는데
      shift+F10으로 테스트해보니
      Unfortunately, ~ has stopped.으로 실행이 안되네요ㅠㅠ
      디바이스설정에서 따로 잡아줘야하는 부분이 있는건가요? 지금 x86 Images에서 Lollipop | 21 | x86_64 | Android 5.0(Google APIs)만 다운해서 적용해서

      Pixel 2 API 21 (Android 5.0.2, API 21)
      로 사용중입니다. 조언부탁드려요ㅠ

      참고로 로그캣에서 붉은색은
      android.process.media에서
      E/SQLiteLog: (1) no such table: files
      com.android.contacts에서
      3956-3963/com.android.contacts E/art: Failed writing handshake bytes (-1 of 14): Broken pipe
      E/eglCodecCommon: glUtilsParamSize: unknow param 0x000082da
      E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008cdf
      E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008824

      com.android.defcontainer에서
      E/art: Failed sending reply to debugger: Broken pipe

      com.android.inputmethod.latin에서
      E/eglCodecCommon: glUtilsParamSize: unknow param 0x000082da
      E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008cdf
      E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008824
      등이 있네요

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.06.08 21:17 신고


        로그캣에서 Error 메시지 부분을 찾아야 합니다.

        앱 실행후 로그캣에 바로 보일겁니다.

      • thx 2019.06.08 23:35


        넵 위에 써놓은것들이 로그캣에서 나온 에러들입니다. 저게 무슨말인지 잘 모르겠어서요 ㅠ

    • Han 2019.06.28 21:01


      포스팅 예제 잘 따라해보았습니다 ~
      다름이 아니라

      FragmentManager fragmentManager = getFragmentManager();
      MapFragment mapFragment = (MapFragment)fragmentManager
      .findFragmentById(R.id.map);

      이 부분에서 FragmentManager 부분에서는
      Incompatible types.
      Required : android.support.v4.app.FragmentManager
      Found : android.app.FragmentManager 라는 오류가 뜨고,

      MapFragment부분에서
      Inconvertible types; cannot cast 'android.support.v4.app.Fragment' to 'com.google.android.gms.maps.MapFragment' 라는 에러가 뜨는데 어떻게 해결해야 할까요 ...?

    • eriot lee 2019.08.14 09:07


      실습을 따라하던중, 문의사항이있습니다.

      현재 mainactivity가 아니라 메인 activity의 하위 activity에서 맵을 구현하고자 하며, extends AppCompatActivity를 사용하고 있습니다.
      implements는 정상적으로 했구요.
      oncreate에서 Fragment manager를 선언하고, mapfragment 선언부까지 따라했는데,
      getMapAsync가 null을 반환한다고 앱이 강제로 종료됩니다. 혹시 이걸 어떻게 해결하는지 여쭤뵈도 될까요?
      아래는 Null 오류 메시지의 일부입니다.
      Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.MapFragment.getMapAsync(com.google.android.gms.maps.OnMapReadyCallback)' on a null object reference

      compile sdkversion 은 29,
      minsdkversion은 22,
      targetsdkversion은 29입니다.
      또한 androidx 라이브러리를 사용하고있습니다.

      • eriot lee 2019.08.14 09:09


        Null 에러 문장이 한문장 더있어서 추가드립니다.
        java.lang.RuntimeException: Unable to start activity ComponentInfo{com.kkk.wherewego/com.kkk.wherewego.NearmeActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.MapFragment.getMapAsync(com.google.android.gms.maps.OnMapReadyCallback)' on a null object reference

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.08.14 11:56 신고


        확인해보니 코드를 그대로 사용하면 api 29에서도 정상 동작합니다.

        에러 가능성이 다음 부분같습니다


        레이아웃에서 다음 부분에 있는 android:id와

        <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.MapFragment" />


        코드에 있는 다음 부분의 id가 동일한가요?

        MapFragment mapFragment = (MapFragment)fragmentManager
        .findFragmentById(R.id.map);

      • eriot lee 2019.08.14 13:23


        예 동일합니다 ㅠㅠ..

        다음은 xml와 activity의 코드 일부입니다

        xml
        <fragment
        android:id="@+id/map"
        class = "com.google.android.gms.maps.MapFragment"
        android:layout_width="346dp"
        android:layout_height="334dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        ...

        activity

        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String NearTag = "";
        TextView now_location;
        FragmentManager fragmentManager = getFragmentManager();
        MapFragment mapFragment = (MapFragment)fragmentManager
        .findFragmentById(R.id.map);

      • eriot lee 2019.08.14 13:32


        확인해보니, 제 코드는 mainactivity가 아니라 NearmeActivity 라는 코드위에서 동작합니다. 그런데 activity java 쪽을 보니
        setContentView(R.layout.activity_main) 이더라구요. 그래서 지금
        setContentView(R.layout.activity_nearme)로 변경하고 경과 확인해보려합니다.

      • eriot lee 2019.08.14 13:34


        해결하였습니다 ㅠㅠㅠㅠ

        첫번째 문제로

        setContentView(R.layout.activity_main)이 문제였었습니다 ㅠㅠ
        그래서 setContentView(R.layout.activity_nearme)로 고쳤고, 그러고나서
        API선언부가 잘못됬다는 에러메시지로 처음으로 바뀌어서 봤더니 geo. 여야하는데 get. 으로 오타를 냈더라구요 ㅠㅠ신경써주셔서 감사합니다 해결했습니다 ㅠㅠ

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.08.14 13:38 신고


        해결해서 다행입니다 : )

      • eriot lee 2019.08.14 13:42


        또한 최초 에러발생이후에 계속 여기저기 보면서 코드를 고쳤었는데 에러원인을 계속 생각해보고 찾았는데, 아무레도 setContentView를 선언하기 전에 Fragmentmanager를 선언해서 발생했었던 문제였던거같아요. 신경써주셔서 감사합니다 ㅠㅠ

    • 11살 아인슈타인 2019.08.14 22:34


      안녕하세요!
      주어진 코드 말고 직접 짠 구글맵 코드로 실행했는데 실제 디바이스에서는 구글맵이 뜨지만 AVD에서는 구글맵이 안 뜨고 강제종료가 됩니다ㅠㅠ
      그리고 로그캣에서 Parameter 'LABEL' not found 오류가 떠요..ㅜㅠ
      어떻게 해결해야 하는지 알 수 있을까요...?

    • 아놔 2019.10.04 14:04


      흠.. 마커찍을 때 서울에 딱 잘 찍긴하는데,
      moveCamera는 경기도를 가리키네요 계속 ㅡㅡ

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.04 14:19 신고


        다음 함수에서 카메라 중심을 마커찍은 곳 근처로 하면 해결될듯합니다.

        mMap.moveCamera(CameraUpdateFactory.newLatLng(SEOUL));


        아니면 마커를 찍은 동안에는 moveCamera를 실행하지 않도록 해보세요.
        그러다가 현재위치 버튼을 누르면 다시 현재 위치를 중심으로 보여주도록..

    • ㅋㅅㅇㅍㄱ 2019.10.21 18:49


      이거 혹시 개인 노트북에서 작업하다가 다른 데스크탑에서 작업하는 등 여러 pc에서 작업할때는 어떻게 해야 하나요? pc 바뀔 때 마다 인증서 새로받고 api키 갱신해야 되는 걸까요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.21 22:24 신고


        인증키 발급받을때 SHA-1을 요구하기때문에 PC마다 새로 인증을 받아야ㅜ하지 않나 싶습니다.

        로컬에서 동작하기때문에 하나의 인증키로 동작할 가능성도 있습니다.
        테스트 해보는 수 밖에 없는듯합니다.

    • Favicon of https://onlyfor-me-blog.tistory.com BlogIcon 끌어주면좀죽여라 2019.11.16 18:18 신고


      이 글을 보고 20년 전 처음 먹어봤다가 소화불량을 일으켰던 시금치가 소화되는 기분을 느꼈습니다. 감사합니다 :)

    • 222 2019.11.16 22:46


      아.. 저는 왜 똑같이 따라했는데 자꾸 앱종료가 뜨죠 ㅠㅠ

      package com.example.googlemap;

      import androidx.appcompat.app.AppCompatActivity;

      import android.app.FragmentManager;
      import android.os.Bundle;

      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.LatLng;
      import com.google.android.gms.maps.model.Marker;
      import com.google.android.gms.maps.model.MarkerOptions;

      public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {

      private FragmentManager fragmentManager;
      private MapFragment mapFragment;

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

      fragmentManager=getFragmentManager();
      mapFragment=(MapFragment)fragmentManager.findFragmentById(R.id.googleMap);
      mapFragment.getMapAsync(this);
      }

      @Override
      public void onMapReady(GoogleMap googleMap) {

      LatLng location = new LatLng(37.562219, 126.986498);

      MarkerOptions markerOptions = new MarkerOptions();
      markerOptions.title("피부과");
      markerOptions.position(location);

      googleMap.addMarker(markerOptions);

      googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(location, 16));
      }

      이렇게 하면 지도에 뜹니다

      근데 올려주신 코드대로하면 안떠요 ㅠㅠ

    • GINI 2019.11.18 20:43


      안녕하세용 android studio가 처음이라 잘 모르는데,,

      Manifest merger failed : Attribute application@appComponentFactory value=(android.support.v4.app.CoreComponentFactory) from [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91
      is also present at [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 value=(androidx.core.app.CoreComponentFactory).
      Suggestion: add 'tools:replace="android:appComponentFactory"' to <application> element at AndroidManifest.xml:7:5-26:19 to override.

      똑같이 따라했는데 이런 에러가 뜨더라구요.. 어떻게 해결할 수 있을까여?

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


        포스트에선 androidx를 사용하고 있는데 생성하신 안드로이드 프로젝트는 android.support를 사용해서 발생한 문제 같습니다.

        androidx를 사용하도록 안드로이드 프로젝트를 생성하여 진행하세요.

        프로젝트 생성시 androidx 체크하는게 있습니다.

        혹은 andoird 9.0 부터는 강제로 사용하게 될겁니다.

    • ohaeori 2019.11.22 16:44


      안녕하세요 안스로 어플 개발을 하고싶은 학생입니다.
      3.3의 결과와 같은 화면이 뜨는데 인증서와 패키지는 정확하게 넣었습니다. 해당 오류에 대해 다른 해결방법이 있나요?

      • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.22 22:58 신고


        인증 오류같습니다.
        로그캣에 다음과 같은 메시지가 있나 다시 확인해보세요..

        2019-05-06 20:34:07.783 9692-11591/com.tistory.webnautes.googlemapsandroidapiexample E/Google Maps Android API: Authorization failure. Please see https://developers.google.com/maps/documentation/android-api/start for how to correctly set up the map.

        2019-05-06 20:34:07.785 9692-11591/com.tistory.webnautes.googlemapsandroidapiexample E/Google Maps Android API: In the Google Developer Console (https://console.developers.google.com)

        Ensure that the "Google Maps Android API v2" is enabled.

        Ensure that the following Android Key exists:

        API Key: 구글맵을 위해 사용중인 API 키

        Android Application (<cert_fingerprint>;<package_name>): SHA1;com.tistory.webnautes.googlemapsandroidapiexample

    • erty 2019.12.05 15:31


      안녕하세요 안드로이드 화면을 반으로 갈라서 위에는 지도, 밑에는 추가정보를 입력하고 싶은데 어떻게 해야하나요??? "~~~를 써야된다" 이 정도 조언만 해주시면 제가 나머지는 할수 있을것 같습니다ㅠㅠ 아예 모르니 검색 키워드도 어떻게 해야할지 모르겠네요ㅜㅜ

    • jmh 2019.12.21 17:35


      안녕하세요 덕분에 원하는 앱을 만들 수 있었습니다.
      애뮬레이터에서는 맵이 아주 잘 뜨는데
      apk추출을 해서 실행을 하면 왼쪽밑에 작게 Google만 보이고 맵이 실행되지 않았습니다.
      또한 어느 폰에서는 패키지가 손상되 깔리지 않았고 깔려도 위에 같이 실행이 되지않았습니다ㅜㅜ

Designed by Tistory.