print("와챠의 개발 기록장")

[안드로이드] 한국관광공사 Tour API 활용하기(지역기반 관광정보조회) - JSON 데이터 가져오기 본문

코딩 일기장/Android(Kotlin)

[안드로이드] 한국관광공사 Tour API 활용하기(지역기반 관광정보조회) - JSON 데이터 가져오기

minWachya 2021. 6. 23. 13:05
반응형

한국관광공사 API 어떻게 쓰는지 연습을 해봤다.

 

실행 결과

이 데이터엔 상세 주소가 없어서 저렇게 나머지 부분만 나왔다.

 

 

AndroidManifest

API 가져오고 url로 된 사진 이용하기 위해

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 추가하고

<application 안에
android:usesCleartextTraffic="true" 추가하기

 

blide.gradle(:app)의 dependencies에 

// api 가져오기
implementation 'com.squareup.retrofit2:retrofit:2.8.0'
implementation 'com.squareup.retrofit2:converter-gson:2.8.0'

implementation 'com.github.bumptech.glide:glide:4.12.0' // 사진 가져오기

추가!!

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<ImageView
android:id="@+id/imgFirstImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher_foreground"
android:layout_weight="6"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_weight="4">
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="제목"
android:textSize="20sp"
android:layout_marginBottom="20dp"/>
<TextView
android:id="@+id/tvAdd1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="주소"/>
<TextView
android:id="@+id/tvAdd2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="상세 주소"/>
</LinearLayout>
</LinearLayout>

 

TravelIntetface.kt

package com.example.mytravel
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query
// 11 - [지역기반 관광정보 조회]
// 결과 xml파일에 접근해서 정보 가져오기 위한 요청 메시지에 필요한 것들
interface TravelIntetface {
@GET("areaBasedList?serviceKey=서비스 키 ")
fun GetTravle(@Query("numOfRows") num_of_rows : Int, // 한 페이지 결과 수
@Query("pageNo") page_no : Int, // 페이지 번호
@Query("MobileOS") mobile_os : String, // OS 구분(필수)
@Query("MobileApp") mobile_app : String, // 서비스명=어플명(필수)
@Query("listYN") list_yn : String, // 목록 구분
@Query("arrange") arrange : String, // 정렬 구분
@Query("contentTypeId") content_type_id : Int, // 관광 타입ID
@Query("areaCode") area_code : Int, // 지역 코드
@Query("sigunguCode") sigungu_code : Int, // 시군구 코드
// @Query("cat1") cat1 : String, // 대분류
// @Query("cat2") cat2 : String, // 중분류
// @Query("cat3") cat3 : String, // 소분류
// @Query("modifiedtime") modifiedtime : String, // 수정일
@Query("_type") type : String)
: Call<TRAVEL>
}

 

MainAvtivity.kt

package com.example.mytravel
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.ImageView
import android.widget.TextView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import retrofit2.Call
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
// xml 파일 형식을 data class로 구현
data class TRAVEL (val response : RESPONSE)
data class RESPONSE(val header : HEADER, val body : BODY)
data class HEADER(val resultCode : String, val resultMsg : String)
data class BODY(val items : ITEMS, val numOfRows : String)
data class ITEMS(val item : ArrayList<ITEM>) // !!! 자료 1개면 배열이면 안 됨 data class ITEMS(val item : ITEM) !!!
// add1 : 주소, add2 : 상세 주소, title : 제목, firstimage : 사진만 가져올 거라서 이정도만!
data class ITEM(val addr1 : String, val addr2 : String, val title : String, val firstimage : String)
// retrofit을 사용하기 위한 빌더 생성
private val retrofit = Retrofit.Builder()
.baseUrl("http://api.visitkorea.or.kr/openapi/service/rest/KorService/")
.addConverterFactory(GsonConverterFactory.create())
.build()
object ApiObject {
val retrofitService: TravelIntetface by lazy {
retrofit.create(TravelIntetface::class.java)
}
}
class MainActivity : AppCompatActivity() {
val num_of_rows = 10
val page_no = 1
val mobile_os = "AND"
val mobile_app = "AppTest"
val list_yn = "Y"
val arrange = "A"
val content_type_id = 15
val area_code = 3
val sigungu_code = 4
// val cat1 = ""
// val cat2 = ""
// val cat3 = ""
// val modifiedtime = ""
val type = "json"
lateinit var tvAdd1 : TextView
lateinit var tvAdd2 : TextView
lateinit var tvTitle : TextView
lateinit var imgFirstImage : ImageView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tvAdd1 = findViewById(R.id.tvAdd1)
tvAdd2 = findViewById(R.id.tvAdd2)
tvTitle = findViewById(R.id.tvTitle)
imgFirstImage = findViewById(R.id.imgFirstImage)
// api 가져오기
setTravel()
}
// Travel 정보 가져오기
fun setTravel() {
// 응답 자료 형식 = GetTravle(num_of_rows, page_no, mobile_os, mobile_app,
// list_yn, arrange, content_type_id, area_code, sigungu_code, cat1, cat2, cat3, modifiedtime)
val call = ApiObject.retrofitService.GetTravle(num_of_rows, page_no, mobile_os, mobile_app,
list_yn, arrange, content_type_id, area_code, sigungu_code, type) //, cat1, cat2, cat3, modifiedtime, type)
// 비동기적으로 실행하기
call.enqueue(object : retrofit2.Callback<TRAVEL> {
// 응답 성공 시
override fun onResponse(call: Call<TRAVEL>, response: Response<TRAVEL>) {
if (response.isSuccessful) {
// Travel 정보 가져오기
var it: ArrayList<ITEM> = response.body()!!.response.body.items.item
tvTitle.text = it[2].title
tvAdd1.text = it[2].addr1
tvAdd2.text = it[2].addr2
Glide.with(imgFirstImage)
.load(it[2].firstimage)
.error(R.drawable.ic_launcher_foreground) // 오류 시 이미지
.into(imgFirstImage)
Log.d("mmm check", response.body().toString())
}
}
// 응답 실패 시
override fun onFailure(call: Call<TRAVEL>, t: Throwable) {
Log.d("mmm", "api fail : " + t.message.toString())
}
})
}
}
view raw MainActivity.kt hosted with ❤ by GitHub

실행하면 맨 위 화면처럼 잘 나오긴 하는데

문제가 있다...

▲이렇게 item이 배열이면 LIST<ITEM>을 써야 받아와지고

이렇게 item이 배열이 아니면 ITEM으로 해야 받아와짐....^^;

 

어케 해결해야할까

지금 생각나는 건 TravelIntetface을 2개씩 만들어서... 하나는  Call<TRAVEL1>, 하나는 Call<TRAVEL2> 부르고

TRAVEL도 2개씩 만들고 ITEMS만 바꾸는 건데 이거 넘 비효율적인 거 같아서 고민중이다.

아... 아니면 json이 아니라 xml로 가져오는 방법도 있음...

근데 그러려면 코드 다시 짜야됨;; 일단...해보자

반응형
Comments