티스토리 뷰
서울 열린 데이터 광장 API 발급받기
https://data.seoul.go.kr/ 에 접속을 하고 회원가입을 합니다.
화장실을 검색을 하고
서울시 공중화장실 위치정보를 선택 후에
인증키 신청을 눌러주고 인증키를 신청합니다.
권한 요청 설정
AndroidManifest에 아래의 코드를 작성해줍니다.
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:usesCleartextTraffic="true"
인터넷 사용 권한을 요청하고 usesCleartextTraffic를 true로 설정해줍니다.
usesCleartextTraffic은 예전에는 기본 값이 true였지만 파이부터 기본 값이 false로 변경되어 true로 설정해줘야 됩니다.
usesCleartextTraffic은 일반 HTTP 통신을 허용할지 안 할지를 고르는 것입니다. 따라서 false로 설정 시에 HTTPS 통신만 가능합니다.
AsyncTask를 사용하여 API 연동하기
먼저 Vecter Asset을 추가해줍니다.
그리고 MainActivity에 아래 코드를 작성해줍니다.
발급받은 API 키
val API_KEY = "api 키"
UI가 종료되었을 때 백그라운드 작업을 종료하기 위해서 선언한 변수
var task: ToiletReadTask? = null
서울시 화장실 데이터를 전부 저장할 변수
var toilets = JSONArray()
화장실 위치 이미지로 사용할 비트맵 선언 코드
val bitmap by lazy {
val bitmap = ResourcesCompat.getDrawable(resources, R.drawable.ic_person_black_24dp, null)?.toBitmap()
Bitmap.createScaledBitmap(bitmap!!, 64, 64, false)
}
JSONArray의 객체 병합을 쉽게 하도록 도와주는 확장 합수
fun JSONArray.merge(anotherArray: JSONArray) {
for (i in 0 until anotherArray.length()) {
this.put(anotherArray.get(i))
}
}
API에서 데이터를 읽어오는 함수
fun readData(startIndex: Int, lastIndex: Int): JSONObject {
val url = URL("http://openAPI.seoul.go.kr:8088" + "/${API_KEY}/json/SearchPublicToiletPOIService/${startIndex}/${lastIndex}")
val connection = url.openConnection()
val data = connection.getInputStream().readBytes().toString(charset("UTF-8"))
return JSONObject(data)
}
화장실 개수는 엄청 많지만 한 번에 읽어 올 수 있는 개수는 1000개가 최대여서 재사용을 위해 함수를 분리하였습니다.
화장실 정보를 읽어와 JSONObject로 반환해줍니다.
AsyncTask 클래스
inner class ToiletReadTask : AsyncTask<Void, JSONArray, String>() {
override fun onPreExecute() {
googleMap?.clear()
toilets = JSONArray()
}
override fun doInBackground(vararg params: Void?): String {
val step = 1000
var startIndex = 1
var lastIndex = step
var totalCount = 0
do {
if (isCancelled) break
if (totalCount != 0) {
startIndex += step
lastIndex += step
}
val jsonObject = readData(startIndex, lastIndex)
totalCount = jsonObject.getJSONObject("SearchPublicToiletPOIService").getInt("list_total_count")
val rows = jsonObject.getJSONObject("SearchPublicToiletPOIService").getJSONArray("row")
toilets.merge(rows)
publishProgress(rows)
} while (lastIndex < totalCount)
return "complete"
}
override fun onProgressUpdate(vararg values: JSONArray?) {
val array = values[0]
array?.let {
for (i in 0 until array.length()) {
addMarkers(array.getJSONObject(i))
}
}
}
}
onPreExecute에서 기존 데이터를 초기화해줍니다.
val step = 1000
var startIndex = 1
var lastIndex = step
var totalCount = 0
doInBackground에서는 데이터를 최대 1000개씩 가져올 수 있기 때문에 여러분 호출하기 위해 위와 같이 선언을 했습니다.
val jsonObject = readData(startIndex, lastIndex)
totalCount = jsonObject.getJSONObject("SearchPublicToiletPOIService").getInt("list_total_count")
val rows = jsonObject.getJSONObject("SearchPublicToiletPOIService").getJSONArray("row")
toilets.merge(rows)
publishProgress(rows)
startIndex와 lastIndex로 데이터를 조회하고 totalCount와 데이터 집합을 가져옵니다.
그리고 merge로 병합하고 UI 업데이트를 위해 progress를 발행합니다.
val array = values[0]
array?.let {
for (i in 0 until array.length()) {
addMarkers(array.getJSONObject(i))
}
onProgressUpdate는 데이터를 읽어오는 중간중간 실행을 해줍니다.
따라서 onProgressUpdate를 사용하여 마커를 추가해줍니다.
onProgressUpdate에서 쓰인 vararg은 개수를 늘릴 수 있는 가변 파라미터입니다.
onStart와 onStop 함수
override fun onStart() {
super.onStart()
task?.cancel(true)
task = ToiletReadTask()
task?.execute()
}
override fun onStop() {
super.onStop()
task?.cancel(true)
task = null
}
마커를 추가하는 함수
fun addMarkers(toilet: JSONObject) {
googleMap?.addMarker(
MarkerOptions()
.position(LatLng(toilet.getDouble("Y_WGS84"), toilet.getDouble("X_WGS84")))
.title(toilet.getString("FNAME"))
.snippet(toilet.getString("ANAME"))
.icon(BitmapDescriptorFactory.fromBitmap(bitmap))
)
}
이제 실행을 하게 되면 지도에 화장실이 표시됩니다.
예제 코드
https://github.com/Im-Tae/Blog_Example/tree/master/Android/Google_Map_Example
'알려주는 이야기 > 안드로이드' 카테고리의 다른 글
안드로이드 구글 지도 사용하기 - 4 [검색 기능] (0) | 2020.06.07 |
---|---|
안드로이드 구글 지도 사용하기 - 3 [클러스터링 사용하기] (0) | 2020.06.06 |
안드로이드 구글 지도 사용하기 - 1 [구글 지도 띄우기] (0) | 2020.06.06 |
코틀린 DataBinding 예제 (0) | 2020.05.04 |
안드로이드 STT, TTS 예제 (0) | 2020.05.02 |