외로운 Nova의 작업실

안드로이드 앱 프로그래밍 - 39(구글맵 사용하기) 본문

Programming/Kotlin - Android

안드로이드 앱 프로그래밍 - 39(구글맵 사용하기)

Nova_ 2023. 3. 10. 16:40

- 구글맵 API 키 얻기

구글맵을 앱에서 사용하려면 구글맵 키가 필요합니다. 아래 링크로 들어가서 포스팅을 보고 따라하시면됩니다.

https://furang-note.tistory.com/16

 

[Android/Kotlin] Google Maps API 사용하기

현재 진행 중인 프로젝트에 지도API가 필요해서 Fragment에 Google Maps를 보여주는 방법을 기록한다. 1. Google API 프로젝트 생성 및 사용 등록 Google API에 접속하여 프로젝트 만들기를 클릭한다. 새 프로

furang-note.tistory.com

 

- 지도 사용 설정

먼저 그래들 파일에 의존성을 추가해줍니다.

implementation 'com.google.android.gms:play-services:12.0.1'

이제 매니페스트 파일에 퍼미션을 등록해줍니다.

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

그 다음은 구글 지도 API를 이용하는 정보를 매니페스트 파일에 등록시켜줘야합니다. 위치는 application 태그 안입니다.

        <uses-library android:name="org.apache.http.legacy" android:required="false" />
        <meta-data android:name="com.google.android.maps.v2.API_KEY"
            android:value="###발급받은 API 키###" />
        <meta-data android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

 

- 지도 표시하기

지도는 fragemt를 메인 xml에 만들고 name을 "com.google.android.gms.maps.SupportMapFragment" 으로 설정해주면 자동으로 프래그먼트를 보여줍니다. 아래는 메인액티비티.xml입니다.

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:id="@+id/mapView"
    android:name="com.google.android.gms.maps.SupportMapFragment"/>

이렇게만 해주고 xml을 실행하면 지도가 보이지만 아프리카 대륙을 보여줍니다. 따라서 사용자의 위치를 받아서 카메라를 옮겨줘야합니다.

//get map object - oncreate 함수 안에 있어야함
        val MapFragment: SupportMapFragment = supportFragmentManager.findFragmentById(R.id.mapView) as
                SupportMapFragment
        MapFragment.getMapAsync(this)

//move camera
    private fun moveMap(latitude: Double, longitude: Double){
        val latLng = LatLng(latitude, longitude)
        val position = CameraPosition.builder()
            .target(latLng)
            .zoom(16f)
            .build()

        googleMap?.moveCamera(CameraUpdateFactory.newCameraPosition(position))

        val markerOptions = MarkerOptions()
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
        markerOptions.position(latLng)
        markerOptions.title("MyLocation")

        googleMap?.addMarker(markerOptions)
    }


    //map view
    override fun onMapReady(p0: GoogleMap?){
        googleMap = p0
    }

getMapAncy()는 프래그먼트에 맵객체를 뿌려주는 역할을 합니다. onMapReady함수는 맵객체가 준비되었을때 콜백됩니다. 이때 p0에 맵객체가 들어있으며 이 객체를 전역변수 googleMap으로 옮겨줍니다. 이후 moveMap함수를 정의해줍니다. 이때 googleMap 객체를 사용해서 카메라와 마크를 추가해주는 함수를 만들어줍니다. 이제 이 함수를 사용자의 위치를 받은후에 호출해줍니다.

 //init googleApiClient
        val connectionCallback = object: GoogleApiClient.ConnectionCallbacks{
            override fun onConnected(p0: Bundle?) {
                if (ActivityCompat.checkSelfPermission(
                        this@MainActivity,
                        Manifest.permission.ACCESS_FINE_LOCATION
                    ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                        this@MainActivity,
                        Manifest.permission.ACCESS_COARSE_LOCATION
                    ) != PackageManager.PERMISSION_GRANTED
                ) {
                    if(status != PackageManager.PERMISSION_GRANTED){
                        ActivityCompat.requestPermissions(this@MainActivity, arrayOf<String>("android.permission.ACCESS_FINE_LOCATION"), 100)
                    } else{
                        ActivityCompat.requestPermissions(this@MainActivity, arrayOf<String>("android.permission.ACCESS_COARSE_LOCATION"), 200)
                    }
                    return
                }
                providerClient.lastLocation.addOnSuccessListener(this@MainActivity
                ) { p0 ->
                    val latitude = p0.latitude
                    val longitude = p0.longitude

                    moveMap(latitude, longitude)


                }
            }

 

- 전체 코드

아래는 메인 액티비티.kt파일입니다.

class MainActivity : AppCompatActivity(), OnMapReadyCallback{
    var googleMap: GoogleMap? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //get permission
        val status = ContextCompat.checkSelfPermission(this, "android.permission.ACCESS_FINE_LOCATION")
        val status2 = ContextCompat.checkSelfPermission(this, "android.permission.ACCESS_COARSE_LOCATION")
        if(status == PackageManager.PERMISSION_GRANTED && status2 == PackageManager.PERMISSION_GRANTED ){
            Log.d("log","permission granted")

        } else{
            if(status != PackageManager.PERMISSION_GRANTED){
                ActivityCompat.requestPermissions(this, arrayOf<String>("android.permission.ACCESS_FINE_LOCATION"), 100)
        } else{
                ActivityCompat.requestPermissions(this, arrayOf<String>("android.permission.ACCESS_COARSE_LOCATION"), 200)
            }
    }

        //init FusedLocationProviderClient
        val providerClient: FusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)

        //init googleApiClient
        val connectionCallback = object: GoogleApiClient.ConnectionCallbacks{
            override fun onConnected(p0: Bundle?) {
                if (ActivityCompat.checkSelfPermission(
                        this@MainActivity,
                        Manifest.permission.ACCESS_FINE_LOCATION
                    ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                        this@MainActivity,
                        Manifest.permission.ACCESS_COARSE_LOCATION
                    ) != PackageManager.PERMISSION_GRANTED
                ) {
                    if(status != PackageManager.PERMISSION_GRANTED){
                        ActivityCompat.requestPermissions(this@MainActivity, arrayOf<String>("android.permission.ACCESS_FINE_LOCATION"), 100)
                    } else{
                        ActivityCompat.requestPermissions(this@MainActivity, arrayOf<String>("android.permission.ACCESS_COARSE_LOCATION"), 200)
                    }
                    return
                }
                providerClient.lastLocation.addOnSuccessListener(this@MainActivity
                ) { p0 ->
                    val latitude = p0.latitude
                    val longitude = p0.longitude

                    moveMap(latitude, longitude)


                }
            }

            override fun onConnectionSuspended(p0: Int) {
                TODO("Not yet implemented")
            }
        }

        val onConnectionFailedCallback = object: GoogleApiClient.OnConnectionFailedListener{
            override fun onConnectionFailed(p0: ConnectionResult) {
                TODO("Not yet implemented")
            }
        }

        val apiClient: GoogleApiClient = GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(connectionCallback)
            .addOnConnectionFailedListener(onConnectionFailedCallback)
            .build()



        //get Location Provider
        apiClient.connect()

        //get map object
        val MapFragment: SupportMapFragment = supportFragmentManager.findFragmentById(R.id.mapView) as
                SupportMapFragment
        MapFragment.getMapAsync(this)
    }

    //move camera
    private fun moveMap(latitude: Double, longitude: Double){
        val latLng = LatLng(latitude, longitude)
        val position = CameraPosition.builder()
            .target(latLng)
            .zoom(16f)
            .build()

        googleMap?.moveCamera(CameraUpdateFactory.newCameraPosition(position))

        val markerOptions = MarkerOptions()
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
        markerOptions.position(latLng)
        markerOptions.title("MyLocation")

        googleMap?.addMarker(markerOptions)
    }


    //map view
    override fun onMapReady(p0: GoogleMap?){
        googleMap = p0
    }
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
            Log.d("log","permission granted")
        } else{
            Toast.makeText(applicationContext,"해당 권한을 허용해주셔야 앱 사용이 가능합니다.", Toast.LENGTH_SHORT).show()
            ActivityCompat.requestPermissions(this, arrayOf<String>("android.permission.ACCESS_FINE_LOCATION"), 100)
            Log.d("log","permission denied")
        }
        if(grantResults[1] == PackageManager.PERMISSION_GRANTED){
            Log.d("log","permission granted")
        } else{
            Toast.makeText(applicationContext,"해당 권한을 허용해주셔야 앱 사용이 가능합니다.", Toast.LENGTH_SHORT).show()
            ActivityCompat.requestPermissions(this, arrayOf<String>("android.permission.ACCESS_COARSE_LOCATION"), 200)
            Log.d("log","permission denied")
        }
    }
}

아래는 메인액티비티.xml 파일입니다.

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:id="@+id/mapView"
    android:name="com.google.android.gms.maps.SupportMapFragment"/>

 

- 실행 화면

 

Comments