ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [안드로이드] 구글 맵 API 이용하기
    카테고리 없음 2024. 5. 2. 21:36

    사용법

     

    1) Gradle 설정

    우선 Google Map API를 사용하기 위해션 Gradle에 라이브러리를 추가해야 합니다.

    dependencies {
        implementation("com.google.android.gms:play-services-maps:18.2.0")
        implementation("com.google.android.gms:play-services-location:21.2.0")
    }

     

    2) AndroidManifest 설정
    아래처럼 인터넷과 위치를 불러올 수 있는 퍼미션을 추가해야 합니다.

    또한 application 안에 uses-library와 meta-data를 추가해줍니다.

     

    로컬 파일에서 API를 가져오는 방법은 아래 게시글을 참조하면 됩니다.

    https://cosinea.tistory.com/49

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools">
    
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
        <uses-permission android:name="android.permission.INTERNET" />
    
        <application
            android:allowBackup="true"
            android:dataExtractionRules="@xml/data_extraction_rules"
            android:fullBackupContent="@xml/backup_rules"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.Map"
            tools:targetApi="31">
    
            <uses-library
                android:name="org.apache.http.legacy"
                android:required="true" />
    
            <meta-data
                android:name="com.google.android.maps.v2.API_KEY"
                android:value="${GOOGLE_MAP_API}" />
            <meta-data
                android:name="com.google.android.gms.version"
                android:value="@integer/google_play_services_version" />
    
            <activity
                android:name=".MainActivity"
                android:exported="true"
                android:theme="@style/Theme.Map">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    </manifest>

     

    3) activity_main.xml

    아래와 같이 FragmentContainerView를 선언 후

    android:name을 Google의 SupportMapFragment으로 지정해야 합니다.

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/mapFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

     

    4) MainActivity

    아래 내용은 길어서 코드에 주석을 달아 설명하겠습니다.

    class MainActivity : AppCompatActivity(), OnMapReadyCallback {
    
        private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
    
        // GoogleMap 변수로 선언
        private lateinit var googleMap: GoogleMap
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(binding.root)
            checkPermission()
        }
    
        // 퍼미션 있는지 체크 후 없으면 퍼미션 확인 창 띄우기
        private fun checkPermission() {
            val locationPermission = registerForActivityResult(
                ActivityResultContracts.RequestMultiplePermissions()
            ) { results ->
                val hasAllPermission = results.all { it.value }
                if (hasAllPermission) {
                    registerFragment()
                } else {
                    Toast.makeText(this, "권한 승인이 필요합니다.", Toast.LENGTH_LONG).show()
                }
            }
            // 퍼미션 확인 창 띄우기
            locationPermission.launch(
                arrayOf(
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION
                )
            )
        }
        
        // SupportMapFragment으로 파싱 후 getMapAsync을 통해 Fragment에 비동기적으로 맵을 등록해줍니다.
        // 여기서 getMapAsync 인자에 있는 this는 OnMapReadyCallback입니다.
        private fun registerFragment() {
            val supportMapFragment = supportFragmentManager.findFragmentById(R.id.mapFragment) as SupportMapFragment
            supportMapFragment.getMapAsync(this)
        }
        
        // OnMapReadyCallback을 상속받으면 구현할 수 있는 함수입니다.
        // GoogleMap을 사용 가능할 때 호출됩니다.
        // 받은 GoogleMap을 위에 선언했던 변수에 저장합니다.
        override fun onMapReady(googleMap: GoogleMap) {
            this.googleMap = googleMap
            updateLocation()
        }
    
        // 퍼미션을 체크하는 기본 메서드가 너무 길어
        // 따로 퍼미션을 체크하는 구문을 만들어 Supress를 시켰습니다.
        @SuppressLint("MissingPermission")
        private fun updateLocation() {
            // FusedLocationProviderClient를 this(activity)를 기반으로 생성합니다.
            val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
            // 위치는 정확해야 하기 때문에 Priority를 최고로 지정하고 1000밀리세컨드(1초)마다 갱신하는 LocationRequest를 생성합니다. 
            val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 1000).build()
            // 위에서 선언한 주기마다 실행되는 콜백입니다.
            val locationCallback = object : LocationCallback() {
                override fun onLocationResult(locationResult: LocationResult) {
                    // setLastLocation을 이용해 현재 위치를 이동시켜주었습니다.
                    locationResult.locations.forEach(this@MainActivity::setLastLocation)
                }
            }
            if (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION) && hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) {
                // 주기에 따라 위치 요청을 업데이트 해주는 함수입니다.
                fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())
            }
        }
    
        // 퍼미션이 있는지 체크하는 함수입니다.
        private fun hasPermission(permission: String): Boolean {
            return ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
        }
    
        private fun setLastLocation(lastLocation: Location) {
            // LatLng을 받은 위치 기반으로 생성해줍니다.
            val latLng = LatLng(lastLocation.latitude, lastLocation.longitude)
            // LatLng을 기반으로 마커를 생성합니다.
            val markerOptions = MarkerOptions().apply {
                position(latLng)
                title("내 위치")
            }
            // LatLng을 타겟팅하고 줌을 15만큼 땡기는 CameraPosition을 생성합니다.
            val cameraPosition = CameraPosition.Builder().target(latLng).zoom(12f).build()
            // CameraPosition을 기반으로 CameraUpdate를 생성합니다.
            val cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition)
            // 아까 생성한 마커를 추가해줍니다.
            googleMap.addMarker(markerOptions)
            // 화면(카메라)을 CameraUpdate 기반으로 움직입니다.
            googleMap.moveCamera(cameraUpdate)
        }
    }

    안드로이드 에뮬레이터의 위치를 설정하는 기능으로 위치를 옮겼습니다.

Designed by Tistory.