와챠의 우당탕탕 코딩 일기장

[안드로이드] 구글맵 api (2) (가장 최근 위치 가져오기, 현재 위치 요청하기) 본문

코딩 일기장/Android(Kotlin)

[안드로이드] 구글맵 api (2) (가장 최근 위치 가져오기, 현재 위치 요청하기)

minWachya 2021. 5. 21. 21:19
반응형

결과 화면

결과 화면은 위와 같다.

  • +-로 지도 크기 조절 가능
  • 구글 위성 지도/일반 지도 사용 가능
  • 카메라 애니메이션 기능
  • 클릭 시 커스텀 마커(요정 이미지) 보이기

 

 

코드 짜기 전에 설정 먼저 해주기!!!

 

1, 구글맵을 사용하기 위해서

gladle(:app)에

implementation 'com.google.android.gms:play-services-location:16.0.0'
implementation 'com.google.android.gms:play-services-maps:16.1.0'

추가

 

2. 내 위치 찾기할 때 권한 필요해서

implementation 'com.yanzhenjie:permission:2.0.3'

추가

 

https://developers.google.com/maps/documentation/android-sdk/start

내용 참조해서 코드를 짠다.

 

 

 AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mygmap">
<!--glEs 사용 선언, 이 앱이 무슨 기능 사용하는 지 미리 알려줌(glEs 없는 기기는 이 앱 사용 못하게)-->
<uses-feature android:required="true" android:glEsVersion="0x00020000" />
<!--이 프로젝트 패키지.permission.MAPS_RECEIVE(이 패키지가 지도를 받기 위한 권한)-->
<permission android:name="com.example.mygmap.permission.MAPS_RECEIVE" android:label="signature" />
<!--구글맵을 사용하기 위한 기본 권한(안터넷, 네트워크, gsf 리드라는 부분 권한)-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<!--일반 권한 설정(읽고 쓰기, 대략 위치, 상세 위치 허용)-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--실시간 위치 정보 엑세스 권한-->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<!--구글 gms 라이브러리 버전 선언-->
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<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/Theme.MyGMAp">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--맵 라이브러리 이용 선언-->
<uses-library android:name="com.google.android.maps" />
<uses-library android:name="org.apache.http.legacy" android:required="false" />
<!--구글 api 키와 프로젝트 연결-->
<meta-data android:name="com.google.android.maps.v2.API_KEY"
android:value="구글 api 키 여기에 " />
</application>
</manifest>

 

activity_main.xml

오류 떠도 괜찮

<?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"
android:orientation="vertical">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30dp"
android:text="나의 현재 위치"/>
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="나의 현재 위치 찾기"/>
<fragment
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.SupportMapFragment" />
</LinearLayout>

 

MainActivity.kt

package com.example.mygmap
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Looper
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.widget.Button
import android.widget.TextView
import com.google.android.gms.location.*
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.GroundOverlayOptions
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
import com.yanzhenjie.permission.AndPermission
import com.yanzhenjie.permission.runtime.Permission
class MainActivity : AppCompatActivity(), OnMapReadyCallback {
private lateinit var mMap : GoogleMap
private lateinit var fairyMarker : GroundOverlayOptions
lateinit var tv : TextView
lateinit var btn : Button
var locationClient : FusedLocationProviderClient? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tv = findViewById(R.id.tv)
btn = findViewById(R.id.btn)
// 버튼 누르면 내 현재 위치 보이기
btn.setOnClickListener {
requestLocation()
}
// 권한 처리
AndPermission.with(this@MainActivity)
.runtime()
.permission(Permission.Group.LOCATION)
.onGranted { permissions ->
Log.d("mmm", "허용된 권한 갯수 : ${permissions.size}")
}
.onDenied { permissions ->
Log.d("mmm", "거부된 권한 갯수 : ${permissions.size}")
}
val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
mapFragment.getMapAsync(this@MainActivity) // 외부 지도 불러오기 위해
// 현재 사용자 위치로 설정
mapFragment.getMapAsync {
mMap = it // 구글맵 연결(초기화)
try {
// 지도 위에 내 위치 표시
mMap.isMyLocationEnabled = true
} catch (e : SecurityException) {
e.printStackTrace()
}
}
}
// 내 현재 위치 찾기
private fun requestLocation() {
locationClient = LocationServices.getFusedLocationProviderClient(this@MainActivity)
try {
// 1, 가장 최근 위치 구하기
locationClient?.lastLocation?.addOnSuccessListener { location ->
if (location == null) {
tv.text = "최근 위치 확인 실패"
}
else {
tv.text = "최근 위치 확인 성공 : ${location.latitude}, ${location.longitude}"
}
}
// 리스너 실패
?.addOnFailureListener {
tv.text = "최근 위치 확인 시 에러 : ${it.message}"
it.printStackTrace()
}
// 2, 나의 현재 위치 요청
val locationRequest = LocationRequest.create()
locationRequest.run {
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
interval = 60 * 1000 // 요청 간격(1초)
}
val locationCallback = object : LocationCallback() {
// 요청 결과
override fun onLocationResult(p0: LocationResult?) {
p0?.let {
for ((i, location) in it.locations.withIndex()) {
tv.text = "내 위치 : ${location.latitude}, ${location.longitude}"
}
// 내 현재 위치에 마커 보이기
val curPoint = LatLng(it.locations[0].latitude, it.locations[0].longitude)
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(curPoint, 15F))
// 마커 옵션 설정
val myMarker = MarkerOptions()
myMarker.position(curPoint)
myMarker.title("내 위치")
myMarker.icon(BitmapDescriptorFactory.fromResource(R.drawable.sun)) // 마커 이미지
mMap.addMarker(myMarker)
}
}
}
// 내 위치 실시간으로 감지
locationClient?.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())
} catch (e : SecurityException) {
e.printStackTrace()
}
}
// 맵이 준비가 됐을 때
override fun onMapReady(p0: GoogleMap) {
mMap = p0 // 지도 연결
mMap.mapType = GoogleMap.MAP_TYPE_SATELLITE // 위성 사진
mMap.uiSettings.isZoomControlsEnabled = true // 지도 크기 조절 +-
// 월드컵 경기장으로 카메라 이동
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(37.568256, 126.897240), 15F))
// 지도 클릭하면 커스텀 마커 보이기
mMap.setOnMapClickListener { point ->
fairyMarker = GroundOverlayOptions().image(
BitmapDescriptorFactory.fromResource(R.drawable.fairy))
.position(point, 100f, 100f)
mMap.addGroundOverlay(fairyMarker)
}
}
// 지도 타입 메뉴
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
super.onCreateOptionsMenu(menu)
menu!!.add(0, 1, 0, "위성 사진")
menu.add(0, 2, 0, "일반 사진")
var subMenu = menu.addSubMenu("장소 찾기 >>")
subMenu.add(0, 4, 0, "덕성여대")
subMenu.add(0, 5, 0, "월드컵 경기장")
subMenu.add(0, 6, 0, "뚝섬 한강")
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId) {
1 -> { // 위성 사진
mMap.mapType = GoogleMap.MAP_TYPE_SATELLITE
return true
}
2 -> { // 일반 사징
mMap.mapType = GoogleMap.MAP_TYPE_NORMAL
return true
}
4 -> { // 덕성여자대학교
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(37.65204792249971, 127.01628911355638), 15F))
mMap.addMarker(MarkerOptions().position(LatLng(37.65204792249971, 127.01628911355638))
.title("덕성여자대학교"))
return true
}
5 -> { // 월드컵 경기장
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(37.568256, 126.897240), 15F))
mMap.addMarker(MarkerOptions().position(LatLng(37.568256, 126.897240))
.title("월드컵 경기장"))
return true
}
6 -> { // 뚝섬 한강
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(37.532395267970394, 127.07211837762921), 15F))
mMap.addMarker(MarkerOptions().position(LatLng(37.532395267970394, 127.07211837762921))
.title("뚝섬 한강"))
return true
}
}
return false
}
}
view raw MainActivity.kt hosted with ❤ by GitHub

 

반응형
Comments