2024. 5. 7. 19:07, ๐ฑAndroid Study
๋ฐ์ํ
1. ์ง๋ ์ฌ์ฉ ์ค์ ํ๊ธฐ
implementation 'com.google.android.gms:play-services-maps:18.1.0'
implementation 'com.google.android.gms:play-services-location:21.0.1'
- Gradle์ dependencies ํญ๋ชฉ ์ค์
<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"/>
- Manifest ํ์ผ์ permission ์ค์
<uses-library android:name="org.apache.http.legacy" android:required="true"/>
<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"/>
- ๊ตฌ๊ธ ์ง๋ API๋ฅผ ์ด์ฉํ๋ ํค๋ฅผ ๋ฑ๋ก
2. ๊ตฌ๊ธ ๊ฐ๋ฐ์ ์ฝ์์์ ์ง๋ API ํค ์ป๊ธฐ
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.SupportMapFragment"/>
- ๋ ์ด์์ XML ์์ ๊ฐ์ด ์ค์
- ๊ตฌ๊ธ ๊ฐ๋ฐ์ ์ฝ์([console.cloud.google.com](http://console.cloud.google.com/) ์ ์ ํ
ํ๋ก์ ํธ๋ฅผ ์์ฑํ๊ณ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด๋ฅผ ๋ง๋ค๋ฉด ์ง๋ API ํค ๋ฅผ ๋ฐ๊ธ - ๊ตฌ๊ธ ๊ฐ๋ฐ์ ์ฝ์์์ ์ป์ ์ง๋ APIํค๋ฅผ Manifest ํ์ผ์ ๋ฑ๋ก
3. ์ง๋ ์ ์ดํ๊ธฐ
class MainActivity : AppCompatActivity(), OnMapReadyCallback {
var googleMap: GoogleMap? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
(supportFragmentManager.findFragmentById(R.id.mapView) as SupportMapFragment)!!.getMapAsync(this)
// ์ง๋ ๊ฐ์ฒด๋ฅผ ์ด์ฉํ ์ ์๋ ์ํฉ์ด ๋ ๋
override fun onMapReady(p0: GoogleMap?) {
googleMap = p0
}
}
- ์ง๋์ ์ค์ฌ ์ด๋ํ๊ธฐ
- ์ง๋๋ฅผ ์ถ๋ ฅํ๋ ๋ทฐ ๊ฐ์ฒด๋ฅผ ์ป์ด์ผ ํจ
val latLng = LatLng(37.566610, 126.978403)
val position = CameraPosition.Builder()
.target(latLng)
.zoom(18f)
.build()
googleMap?.moveCamera(CameraUpdateFactory.newCameraPosition(position))
- ์ง๋์ ์ค์ฌ์ ์ด๋
val markerOptions = MarkerOptions()
markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_marker))
markerOptions.position(latLng)
markerOptions.title("์์ธ์์ฒญ")
markerOptions.snippet("Tel:01-120")
googleMap?.addMarker(markerOptions)
- ๋ง์ปค ํ์ํ๊ธฐ
val locationRequest = LocationRequest.create().apply {
interval = 1000
fastestInterval = 500
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
locationCallback = object : LocationCallback(){
//1์ด์ ํ๋ฒ์ฉ ๋ณ๊ฒฝ๋ ์์น ์ ๋ณด๊ฐ onLocationResult ์ผ๋ก ์ ๋ฌ๋๋ค.
override fun onLocationResult(locationResult: LocationResult) {
locationResult?.let{
for (location in it.locations){
Log.d("์์น์ ๋ณด", "์๋: ${location.latitude} ๊ฒฝ๋: ${location.longitude}")
}
}
}
}
- ์์น ์์ฒญ
googleMap?.setOnMapClickListener { latLng ->
Log.d("map_test", "click : ${latLng.latitude} , ${latLng.longitude}")
}
googleMap?.setOnMapLongClickListener { latLng ->
Log.d("map_test", "long click : ${latLng.latitude} , ${latLng.longitude}")
}
googleMap?.setOnCameraIdleListener {
val position = googleMap!!.cameraPosition
val zoom = position.zoom
val latitude = position.target.latitude
val longitude = position.target.longitude
Log.d("map_test", "User change : $zoom $latitude , $longitude")
}
googleMap?.setOnMarkerClickListener { marker ->
true
}
googleMap?.setOnInfoWindowClickListener { marker ->
}
- ์ง๋์์ ์ฌ์ฉ์ ์ด๋ฒคํธ ์ฒ๋ฆฌ
- GoogleMap.OnMapClickListener: ์ง๋ ํด๋ฆญ ์ด๋ฒคํธ
- GoogleMap.OnMapLongClickListener: ์ง๋ ๋กฑ ํด๋ฆญ ์ด๋ฒคํธ
- GoogleMap.OnMarkerClickListener: ๋ง์ปค ํด๋ฆญ ์ด๋ฒคํธ
- GoogleMap.OnMarkerDragListener: ๋ง์ปค ๋๋๊ทธ ์ด๋ฒคํธ
- GoogleMap.OnInfoWindowClickListener: ์ ๋ณด ์ฐฝ ํด๋ฆญ ์ด๋ฒคํธ
- GoogleMap.OnCameraIdleListener: ์ง๋ ํ๋ฉด ๋ณ๊ฒฝ ์ด๋ฒคํธ
4. GoogleCloud์์ ์ฌ์ฉ์ ์ธ์ฆํค ๋ง๋ค๊ธฐ
(1) GoogleCloud์ ์ ์ํ์ฌ ๊ตฌ๊ธ ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธ
(2) ์ ํ๋ก์ ํธ ์์ฑ
(3) API ๋ฐ ์๋น์ค -> ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด
(4) ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด ๋ง๋ค๊ธฐ + ๋ฒํผ ํด๋ฆญ > API ํค ํด๋ฆญ
(5) API ํค ์์ฑ
5. Android APP ๋ง๋ค๊ธฐ (์์)
๋๋ณด๊ธฐ
1. ํ๋ก์ ํธ ์์ฑ
2. build.gradle ํ์ผ์ Googlemap ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ
dependencies {
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation 'com.google.android.gms:play-services-maps:18.1.0'
implementation 'com.google.android.gms:play-services-location:21.0.1'
}
3. AndriodManifest.xml ์ permission๊ณผ google-map api ์ถ๊ฐ
googlecloud์์ ์์ฑํ APIํค ์
๋ ฅ
<?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:supportsRtl="true"
android:theme="@style/Theme.MapTest"
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 Cloud์์ ์์ฑํ APIํค ์
๋ ฅ!! ==="/>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.SupportMapFragment"/>
MainActivity.kt
package com.android.ex11_googlemap
import android.Manifest
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.location.Location
import android.os.Bundle
import android.os.Looper
import android.util.Log
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
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.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.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.BitmapDescriptorFactory
import com.google.android.gms.maps.model.CameraPosition
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
import com.google.android.gms.tasks.OnSuccessListener
class MainActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var mGoogleMap: GoogleMap
//์์น ์๋น์ค๊ฐ gps๋ฅผ ์ฌ์ฉํด์ ์์น๋ฅผ ํ์ธ
lateinit var fusedLocationClient: FusedLocationProviderClient
//์์น ๊ฐ ์์ฒญ์ ๋ํ ๊ฐฑ์ ์ ๋ณด๋ฅผ ๋ฐ๋ ๋ณ์
lateinit var locationCallback: LocationCallback
lateinit var locationPermission: ActivityResultLauncher<Array<String>>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
locationPermission = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()){ results ->
if(results.all{it.value}){
(supportFragmentManager.findFragmentById(R.id.mapView) as SupportMapFragment)!!.getMapAsync(this)
}else{ //๋ฌธ์ ๊ฐ ๋ฐ์ํ์ ๋
Toast.makeText(this,"๊ถํ ์น์ธ์ด ํ์ํฉ๋๋ค.",Toast.LENGTH_LONG).show()
}
}
//๊ถํ ์์ฒญ
locationPermission.launch(
arrayOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
)
}
// ์ง๋ ๊ฐ์ฒด๋ฅผ ์ด์ฉํ ์ ์๋ ์ํฉ์ด ๋ ๋
override fun onMapReady(p0: GoogleMap) {
val seoul = LatLng(37.566610, 126.978403)
mGoogleMap = p0
mGoogleMap.mapType = GoogleMap.MAP_TYPE_NORMAL // default ๋
ธ๋ง ์๋ต ๊ฐ๋ฅ
mGoogleMap.apply {
val markerOptions = MarkerOptions()
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))
markerOptions.position(seoul)
markerOptions.title("์์ธ์์ฒญ")
markerOptions.snippet("Tel:01-120")
addMarker(markerOptions)
}
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
updateLocation()
}
fun updateLocation(){
val locationRequest = LocationRequest.create().apply {
interval = 1000
fastestInterval = 500
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
locationCallback = object : LocationCallback(){
//1์ด์ ํ๋ฒ์ฉ ๋ณ๊ฒฝ๋ ์์น ์ ๋ณด๊ฐ onLocationResult ์ผ๋ก ์ ๋ฌ๋๋ค.
override fun onLocationResult(locationResult: LocationResult) {
locationResult?.let{
for (location in it.locations){
Log.d("์์น์ ๋ณด", "์๋: ${location.latitude} ๊ฒฝ๋: ${location.longitude}")
setLastLocation(location) //๊ณ์ ์ค์๊ฐ์ผ๋ก ์์น๋ฅผ ๋ฐ์์ค๊ณ ์๊ธฐ ๋๋ฌธ์ ๋งต์ ํ๋ํด๋ ๋ค์ ์ค์ด๋ ๋ค.
}
}
}
}
//๊ถํ ์ฒ๋ฆฌ
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback,
Looper.myLooper()!!
)
}
fun setLastLocation(lastLocation: Location){
val LATLNG = LatLng(lastLocation.latitude,lastLocation.longitude)
val makerOptions = MarkerOptions().position(LATLNG).title("๋ ์ฌ๊ธฐ ์์ด์ฉ~")
val cameraPosition = CameraPosition.Builder().target(LATLNG).zoom(15.0f).build()
mGoogleMap.addMarker(makerOptions)
mGoogleMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition))
}
}
๋ฐ์ํ
๐ฌ C O M M E N T