유디의 공간정보·개발일기

2.1001_Kotlin으로 Android Studio 프로젝트 생성 본문

지도API

2.1001_Kotlin으로 Android Studio 프로젝트 생성

55yudi 2021. 10. 1. 17:45

안드로이드 스튜디오 설정에서 SDK Manager - SDK Tools

다음 2개 필요한 것 install하기

얘는 옵션 (난 설치가 안된다고 뜸,,)

 

- settings - auto import - kotlin 부분 모두 체크


[ MyLocation ] 프로젝트 생성 : 좌표 가져오기

 

- component tree애서 convert view로 layout 변경 가능

- layout_margin

- padding / paddingLeft / paddingTop / paddingEnd / paddingRight / paddingBottom

 

- res>drawable 폴더에 xml파일을 만들 수 있다.
- 테두리만 있는 버튼 만들어보기 :
  drawable폴더에 new file 로 layer-list 코드 작성 (root element를 selector 대신 layer-list로 해서 만들어도 됨)


- 버튼 선택후 백그라운드에서 이미지 설정



- values > themes > themes.xml 코드 수정
- 기본적으로 있는 바 : 툴바, 액션바 --> 없애려면 다음 코드로 작성(parent속성 수정)

<style name="Theme.MyLocation" parent="Theme.AppCompat.Light.NoActionBar">

- layout_alignParent 속성 true

- layout_centerVertical 속성 true

 

- layout_above에 id가 bottomLayout인 RelativeLayout 지정

- layout_below에 id가 topLayout인 RelativeLayout 지정

--> LinearLayout의 사용할 수 있는 영역을 제한해서 지정해줌

- 버튼과 레이아웃들에 id값 주기, text값, text size, text color, background 지정

 

- 내 위치 버튼을 눌렀을 때 내위치를 찾을 수 있도록 해보기

 

- build.gradle에 코드 추가하고 sync now 클릭

- MainActivity에 코드 추가

- build.gradle에 //위치확인을 위한 implementation 코드 작성 - sync now 클릭

  * 코드에 블럭이 씌워진다면 커서를 갖다댔을 때 최신 버전으로 변경할 수 있게 뜬다.

 

- MainActivity.kt 에 코드 작성, 함수 생성

- 실내로 들어오면 gps가 위치를 못잡기 때문에 마지막 위치를 기억하도록 (null이 아니도록)

 

- AndroidManifest.xml에 코드 추가

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

- 깃허브에 android permission 검색해서 코드 가져와서 사용할 것임

  buildGradle에 위험 권한에 관한 코드 추가

implementation 'com.guolindev.permissionx:permissionx:1.5.1'

- MainActivity.kt에 코드 작성

//위험 권한 부여해보기
        PermissionX.init(this)
            .permissions(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION)
            .request { allGranted, grantedList, deniedList ->
                if (allGranted) {
                    Toast.makeText(this, "모든 권한이 부여됨", Toast.LENGTH_LONG).show()
                } else {
                    Toast.makeText(this, "권한 중에 거부된 권한들 : $deniedList", Toast.LENGTH_LONG).show()
                }
            }

  * jar 말고 andriod 밑의 Manifest로 import할 것!

  - 토스트 메시지로 뜨게 된다.

 

- 애뮬레이터 실행하기

   * 만약 다음 사진처럼 안뜬다면 애뮬레이터 실행 후 제어바 내려서 앱 권한 - 위치로 들어가서 허용해주기

 

- it 이 null인 경우(최근 마지막 위치가 없는 경우)가 있어서 null로 표시되지도 않고 앱이 죽어버림

   --> 코드 it뒤에 ? 추가 --> 앱이 죽지않고 null값으로 뜸

- 애뮬레이터 실행 - 컨트롤바에서 설정 - 위치 지정하고 point 저장하기 - set location 클릭

- 위치 좌표 세이브하기 전에는 애뮬레이터를 실행한 후 내위치 버튼을 눌렀을 때 null값으로 표시됨


- 현재 위치 확인하기 --> LocationRequest 객체를 만들기

// 현재 위치 확인하기
            val locationRequest = LocationRequest.create()
            locationRequest.run {
                priority = LocationRequest.PRIORITY_HIGH_ACCURACY
                interval = 30 * 1000 //30초마다
            }

            val locationCallback = object:LocationCallback() {
                override fun onLocationResult(result: LocationResult) { //파라미터 안에 내 현재위치가 들어있음
                    super.onLocationResult(result)

                    result.run {
                        for ((index, location) in locations.withIndex()) { //반복적으로 실행, 몇 번째인지 index로
                            binding.output1.text = "현재 위치 : ${location.latitude}, ${location.longitude}"
                        }
                    }
                }
            }

            locationClient?.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())

- 애뮬레이터 실행

- null값으로 뜨던 경도, 위도 좌표가 잘 나타난다.


[ MyMap ] 프로젝트 새로 생성 : 지도 띄우기

 

- buildGradle 에 코드 추가

// 위치 확인
implementation 'com.google.android.gms:play-services-location:18.0.0'

// 지도
implementation 'com.google.android.gms:play-services-maps:18.0.0'

// 위험 권한
implementation 'com.guolindev.permissionx:permissionx:1.5.1'

 

- AndroidManifest에 코드 추가

 아래쪽부터 빨간체크 두개는 인터넷을 사용하기 위한 코드

 

 

- file - project structure - dependency - app - play-services-maps치고 검색

  services-maps 17.0.1 라이브러리 설치

 

- AndroidManifest에 코드 작성

- API 키를 발급받아서 android:key 에 넣어줘야 함

- API키 발급받기 : 

  구글 클라우드 들어가서 APIs&서비스 - 라이브러리

 

Maps SDK for Android 클릭 - 활성화

 

사용자인증 생성 으로 키값 복사해서 name에 넣어주기

 

- 마커할 이미지(location.png) 가져와서 넣어주기

- 함수 코드 추가

 

- 애뮬레이터 실행

- 지도 위에 png 이미지가 중첩되어 좌표 위에 잘 나타난다.


MainActivity 전체 코드

package com.lx.map

import android.Manifest
import android.location.Location
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Looper
import android.widget.Toast
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.SupportMapFragment
import com.google.android.gms.maps.model.BitmapDescriptorFactory
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
import com.lx.map.databinding.ActivityMainBinding
import com.permissionx.guolindev.PermissionX

class MainActivity : AppCompatActivity() {
    lateinit var binding: ActivityMainBinding

    lateinit var map: GoogleMap
    var locationClient: FusedLocationProviderClient? = null //아무값도 아니게 초기화작업

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 지도 초기화하기
        // Fragment라는 구분화면을 이렇게 찾고 --> 변수상자에 넣어줌
        val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync {
            map = it //지도의 초기화가 끝나면 구글맵 객체가 붕어빵처럼 들어가있음

            requestLocation()
        }

        //위험 권한 부여하기
        PermissionX.init(this)
            .permissions(
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION
            )
            .request { allGranted, grantedList, deniedList ->
                if (allGranted) {
                    Toast.makeText(this, "모든 권한이 부여됨", Toast.LENGTH_LONG).show()
                } else {
                    Toast.makeText(this, "권한 중에 거부된 권한들 : $deniedList", Toast.LENGTH_LONG).show()
                }
            }
    }

        fun requestLocation() {
            // 위치 클라이언트 가져오기
            locationClient = LocationServices.getFusedLocationProviderClient(this)

            try {
                //최근 위치 확인하기 : 마지막 위치가 성공적으로 전달된다면
                locationClient?.lastLocation?.addOnSuccessListener { //권한이 없어서 오류나므로 권한주기(->Manifest.xml)
                    println("최근 위치 : ${it?.latitude}, ${it?.longitude}")
                }?.addOnFailureListener {
                    println("최근 위치 확인 시 에러 : ${it.message}")
                }

                // 현재 위치 확인하기
                val locationRequest = LocationRequest.create()
                locationRequest.run {
                    priority = LocationRequest.PRIORITY_HIGH_ACCURACY
                    interval = 30 * 1000 //30초마다
                }

                val locationCallback = object: LocationCallback() {
                    override fun onLocationResult(result: LocationResult) { //파라미터 안에 내 현재위치가 들어있음
                        super.onLocationResult(result)

                        result.run {
                            for ((index, location) in locations.withIndex()) { //반복적으로 실행, 몇 번째인지 index로
                                println("현재 위치 : ${location.latitude}, ${location.longitude}")

                                showCurrentLocation(location)
                            }
                        }
                    }
                }

                locationClient?.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper())

            } catch(e:SecurityException) {
                e.printStackTrace()
            }
        }

        fun showCurrentLocation(location: Location) {
            val curPoint = LatLng(location.latitude, location.longitude)
            map.moveCamera(CameraUpdateFactory.newLatLngZoom(curPoint, 17.0f))

            showMarker(curPoint)
        }

        // 지도 위에 마커 표시해보기
        fun showMarker(curPoint:LatLng) {
            val myMarker = MarkerOptions()
            // with : 필요한 설정들을 모아줌
            with(myMarker) {
                position(curPoint)
                title("내 위치")
                icon(BitmapDescriptorFactory.fromResource(R.drawable.location))
                map.addMarker(this)
            }
        }
}

 

* 함수인식이 안될 때는 중괄호 위치 잘 살펴보기!

 

* with 코드 블록 :

   - 이미 만들어져 있는 객체(여기에서는 myMarker)에 접근하는 경우 반복되는 코드가 발생되는데

      with 코드블록을 이용해 객체 접근 코드를 중괄호로 그룹화할 수 있다.


리사이클러 뷰 사용해서 왼쪽에는 지도, 오른쪽에는 메뉴목록처럼 List로 나타내기

 

- 리사이클러 뷰 참고 :

https://wooooooak.github.io/android/2019/03/28/recycler_view/

 

RecyclerView(리사이클러뷰)의 원리와 사용법(feat. Kotlin) · 쾌락코딩

RecyclerView(리사이클러뷰)의 원리와 사용법(feat. Kotlin) 28 Mar 2019 | recycler_view kotlin 카카오톡의 채팅 대화방, pinterest 앱의 수 많은 리스트 데이터들을 효율적으로 렌더링 하기 위해서 안드로이드에

wooooooak.github.io

 

- 장소 검색 결과를 리사이클러 뷰에 추가 참고 :

https://mechacat.tistory.com/16

 

[Android/KakaoAPI] 장소 검색 결과를 리사이클러 뷰에 추가

이전 글에서는 REST API를 이용해 장소 검색 결과를 받아오는 것을 해봤고, 이번에는 받아온 결과를 리사이클러 뷰에 추가하는 것과, 추가된 아이템 클릭 시 해당 장소로 이동하는 것을 만들어봤

mechacat.tistory.com

 

'지도API' 카테고리의 다른 글

5. 1006_ 안드로이드 앱 화면  (0) 2021.10.06
4. 1005_ Fragment  (0) 2021.10.05
3. 1004_RecyclerView, Adapter, SQL로 좌표 쿼리문, tab  (0) 2021.10.04
1. 0929_App, 아이디어회의  (0) 2021.09.29