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

[안드로이드] 최신 기상청 단기예보 API 활용하기(초단기예보, Json) 본문

코딩 일기장/Android(Kotlin)

[안드로이드] 최신 기상청 단기예보 API 활용하기(초단기예보, Json)

minWachya 2021. 7. 30. 16:47
반응형

올해 1학기 때 과제로 기상청 동네 예보 API를 사용한 적이 있었는데...

7월 초에 이런 메일이 왔다.

동네 예보 API가 종료된다고...

물론 단기 예보 단위가 상세화 되는 건 좋다~

기존에 있던 코드 바꾸는 게 귀찮을 뿐임

암튼 잘 쓰고 있던 API라 수정도 해보고 위젯같은 기능들도 추가해보려고 한다!!

 

일단 바뀐 API 부터 적용해보자.

 

나는 기존 API에서는 4시간 단위로 날씨 정보를 주는 동네예보를 사용했는데,

변경된 API에서는 1시간 단위로 날씨 정보를 주는 초단기예보를 사용해서 앱을 만들어보려고 한다!!

 

코드에 주석으로 간단히 설명했고 자세한 설명은 블로그 아래에 써놨다.


근데 전에 게시글(이전 기상청 동네 예보 API 사용)이랑 비슷한 부분이 많음!

https://min-wachya.tistory.com/129

 

[안드로이드] 기상청 동네예보 API 활용하기

아래의 앱을 만들어 볼 것이다. 원래는 흰 배경에 검정 글씨인데 지금 내 폰이 다크모드라 저렇게 됐다. 신기... 공공 데이터 포탈에서 아래 API를 검색한 후 활용 신청하기!! AndroidManifest.xml 설정

min-wachya.tistory.com


실행 결과

실행 결과

현재 시간대 날씨 정보 1개 + 1시간 뒤의 날씨 정보가 5개씩해서 총 6개의 날씨 정보가 보여지는 것부터...시작했다.

그리고 각 온도에 맞춰서 옷 추천하는 것도 넣어봤다. 옷 추천은 나중에 위젯에도 활용할 거임!


먼저 공공데이터 포탈에서 활용신청 하기

 

AndroidManifest.xml 설정하기

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myweathertest2">
<!--날씨 API 가져오기-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:usesCleartextTraffic="true"
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.AppCompat.Light.NoActionBar"> <!--액션바 안보이게-->
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--위젯-->
<receiver android:name="WeatherAppWidgetProvider" android:enabled="true" android:exported="true" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/weather_appwidget_info" />
</receiver>
</application>
</manifest>

 

1)

manifest-application에
android:usesCleartextTraffic="true" 추가

 

2)

인터넷과 네트워크 연결 위해

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

 

3)

액션바 안 보이게 하기

android:theme="@style/Theme.AppCompat.Light.NoActionBar"

 

(위젯 부분은 나중에 다룸)

 

grable(:app) 설정하기

Json 데이터를 쉽게 가져오기 위해

implementation 'com.squareup.retrofit2:retrofit:2.8.0'
implementation 'com.squareup.retrofit2:converter-gson:2.8.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:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/tvDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="mm/dd의 날씨"
android:textSize="30dp"
android:textColor="@color/black"
android:layout_margin="10dp"
android:gravity="center"/>
<TextView
android:id="@+id/tvError"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="에러 : "
android:textSize="30dp"
android:textColor="@color/black"
android:layout_margin="10dp"
android:gravity="center"
android:visibility="gone"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/weatherRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
<Button
android:id="@+id/btnRefresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="새로고침"/>
</LinearLayout>


list_item_weather.xml : 리사이클러뷰에 들어갈 아이템뷰

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_margin="20dp">
<TextView
android:id="@+id/tvTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="00시 날씨"
android:textColor="@color/black"
android:textSize="24dp"
android:layout_marginBottom="10dp"/>
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#ddeeff">
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="강수 형태"
android:textSize="20dp"
android:paddingRight="30dp"/>
<TextView
android:id="@+id/tvRainType"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textSize="20dp"/>
</TableRow>
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="습도"
android:textSize="20dp"
android:paddingRight="30dp"/>
<TextView
android:id="@+id/tvHumidity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textSize="20dp"/>
</TableRow>
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="하늘 상태"
android:textSize="20dp"
android:paddingRight="30dp"/>
<TextView
android:id="@+id/tvSky"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textSize="20dp"/>
</TableRow>
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="기온"
android:textSize="20dp"
android:paddingRight="30dp"/>
<TextView
android:id="@+id/tvTemp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textSize="20dp"/>
</TableRow>
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="옷 추천"
android:textSize="20dp"
android:paddingRight="30dp"/>
<TextView
android:id="@+id/tvRecommends"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textSize="20dp"/>
</TableRow>
</TableLayout>
</LinearLayout>


ModelWeather.kt : 날씨 정보가 담길 클래스

package com.example.myweathertest2.Model
// 날씨 정보를 담는 데이터 클래스
class ModelWeather {
var rainType = "" // 강수 형태
var humidity = "" // 습도
var sky = "" // 하능 상태
var temp = "" // 기온
var fcstTime = "" // 예보시각
}
view raw ModelWeather.kt hosted with ❤ by GitHub


WeatherAdpater.kt : 리사이클러뷰에 들어갈 아이템뷰 설정해주는 부분

package com.example.myweathertest2.Adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.myweathertest2.Model.ModelWeather
import com.example.myweathertest2.R
class WeatherAdapter (var items : Array<ModelWeather>) : RecyclerView.Adapter<WeatherAdapter.ViewHolder>() {
// 뷰 홀더 만들어서 반환, 뷰릐 레이아웃은 list_item_weather.xml
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WeatherAdapter.ViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.list_item_weather, parent, false)
return ViewHolder(itemView)
}
// 전달받은 위치의 아이템 연결
override fun onBindViewHolder(holder: WeatherAdapter.ViewHolder, position: Int) {
val item = items[position]
holder.setItem(item)
}
// 아이템 갯수 리턴
override fun getItemCount() = items.count()
// 뷰 홀더 설정
inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {
fun setItem(item : ModelWeather) {
val tvTime = itemView.findViewById<TextView>(R.id.tvTime) // 시각
val tvRainType = itemView.findViewById<TextView>(R.id.tvRainType) // 강수 형태
val tvHumidity = itemView.findViewById<TextView>(R.id.tvHumidity) // 습도
val tvSky = itemView.findViewById<TextView>(R.id.tvSky) // 하늘 상태
val tvTemp = itemView.findViewById<TextView>(R.id.tvTemp) // 온도
val tvRecommends = itemView.findViewById<TextView>(R.id.tvRecommends) // 옷 추천
tvTime.text = item.fcstTime
tvRainType.text = getRainType(item.rainType)
tvHumidity.text = item.humidity
tvSky.text = getSky(item.sky)
tvTemp.text = item.temp + "°"
tvRecommends.text = getRecommends(item.temp.toInt())
}
}
// 강수 형태
fun getRainType(rainType : String) : String {
return when(rainType) {
"0" -> "없음"
"1" -> "비"
"2" -> "비/눈"
"3" -> "눈"
else -> "오류 rainType : " + rainType
}
}
// 하늘 상태
fun getSky(sky : String) : String {
return when(sky) {
"1" -> "맑음"
"3" -> "구름 많음"
"4" -> "흐림"
else -> "오류 rainType : " + sky
}
}
// 옷 추천
fun getRecommends(temp : Int) : String{
return when (temp) {
in 5..8 -> "울 코트, 가죽 옷, 기모"
in 9..11 -> "트렌치 코트, 야상, 점퍼"
in 12..16 -> "자켓, 가디건, 청자켓"
in 17..19 -> "니트, 맨투맨, 후드, 긴바지"
in 20..22 -> "블라우스, 긴팔 티, 슬랙스"
in 23..27 -> "얇은 셔츠, 반바지, 면바지"
in 28..50 -> "민소매, 반바지, 린넨 옷"
else -> "패딩, 누빔 옷, 목도리"
}
}
}


WeatherInterface.kt : xml 접근 준비 & xml 파일 형식 data class로 구현한 부분

package com.example.myweathertest2
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query
// 결과 xml 파일에 접근해서 정보 가져오기
interface WeatherInterface {
// getUltraSrtFcst : 초단기 예보 조회 + 인증키
@GET("getUltraSrtFcst?serviceKey=서비스키_여기에_")
fun GetWeather(@Query("numOfRows") num_of_rows : Int, // 한 페이지 경과 수
@Query("pageNo") page_no : Int, // 페이지 번호
@Query("dataType") data_type : String, // 응답 자료 형식
@Query("base_date") base_date : String, // 발표 일자
@Query("base_time") base_time : String, // 발표 시각
@Query("nx") nx : String, // 예보지점 X 좌표
@Query("ny") ny : String) // 예보지점 Y 좌표
: Call<WEATHER>
}
// xml 파일 형식을 data class로 구현
data class WEATHER (val response : RESPONSE)
data class RESPONSE(val header : HEADER, val body : BODY)
data class HEADER(val resultCode : Int, val resultMsg : String)
data class BODY(val dataType : String, val items : ITEMS, val totalCount : Int)
data class ITEMS(val item : List<ITEM>)
// category : 자료 구분 코드, fcstDate : 예측 날짜, fcstTime : 예측 시간, fcstValue : 예보 값
data class ITEM(val category : String, val fcstDate : String, val fcstTime : String, val fcstValue : String)
// retrofit을 사용하기 위한 빌더 생성
private val retrofit = Retrofit.Builder()
.baseUrl("http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/")
.addConverterFactory(GsonConverterFactory.create())
.build()
object ApiObject {
val retrofitService: WeatherInterface by lazy {
retrofit.create(WeatherInterface::class.java)
}
}


MainActivity.kt : API 가져와서 ModelWeather에 날씨 정보 넣고 리사이클러뷰 설정한 부분

package com.example.myweathertest2
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.myweathertest2.Adapter.WeatherAdapter
import com.example.myweathertest2.Model.ModelWeather
import retrofit2.Call
import retrofit2.Response
import java.text.SimpleDateFormat
import java.util.*
// 메인 액티비티
class MainActivity : AppCompatActivity() {
lateinit var weatherRecyclerView : RecyclerView
private var base_date = "20210510" // 발표 일자
private var base_time = "1400" // 발표 시각
private var nx = "55" // 예보지점 X 좌표
private var ny = "127" // 예보지점 Y 좌표
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val tvDate = findViewById<TextView>(R.id.tvDate) // 오늘 날짜 텍스트뷰
weatherRecyclerView = findViewById<RecyclerView>(R.id.weatherRecyclerView) // 날씨 리사이클러 뷰
val btnRefresh = findViewById<Button>(R.id.btnRefresh) // 새로고침 버튼
// 리사이클러 뷰 매니저 설정
weatherRecyclerView.layoutManager = LinearLayoutManager(this@MainActivity)
// 오늘 날짜 텍스트뷰 설정
tvDate.text = SimpleDateFormat("MM월 dd일", Locale.getDefault()).format(Calendar.getInstance().time) + "날씨"
// nx, ny지점의 날씨 가져와서 설정하기
setWeather(nx, ny)
// <새로고침> 버튼 누를 때 날씨 정보 다시 가져오기
btnRefresh.setOnClickListener {
setWeather(nx, ny)
}
}
// 날씨 가져와서 설정하기
private fun setWeather(nx : String, ny : String) {
// 준비 단계 : base_date(발표 일자), base_time(발표 시각)
// 현재 날짜, 시간 정보 가져오기
val cal = Calendar.getInstance()
base_date = SimpleDateFormat("yyyyMMdd", Locale.getDefault()).format(cal.time) // 현재 날짜
val timeH = SimpleDateFormat("HH", Locale.getDefault()).format(cal.time) // 현재 시각
val timeM = SimpleDateFormat("HH", Locale.getDefault()).format(cal.time) // 현재 분
// API 가져오기 적당하게 변환
base_time = getBaseTime(timeH, timeM)
// 현재 시각이 00시이고 45분 이하여서 baseTime이 2330이면 어제 정보 받아오기
if (timeH == "00" && base_time == "2330") {
cal.add(Calendar.DATE, -1).toString()
base_date = SimpleDateFormat("yyyyMMdd", Locale.getDefault()).format(cal.time)
}
// 날씨 정보 가져오기
// (한 페이지 결과 수 = 60, 페이지 번호 = 1, 응답 자료 형식-"JSON", 발표 날싸, 발표 시각, 예보지점 좌표)
val call = ApiObject.retrofitService.GetWeather(60, 1, "JSON", base_date, base_time, nx, ny)
// 비동기적으로 실행하기
call.enqueue(object : retrofit2.Callback<WEATHER> {
// 응답 성공 시
override fun onResponse(call: Call<WEATHER>, response: Response<WEATHER>) {
if (response.isSuccessful) {
// 날씨 정보 가져오기
val it: List<ITEM> = response.body()!!.response.body.items.item
// 현재 시각부터 1시간 뒤의 날씨 6개를 담을 배열
val weatherArr = arrayOf(ModelWeather(), ModelWeather(), ModelWeather(), ModelWeather(), ModelWeather(), ModelWeather())
// 배열 채우기
var index = 0
val totalCount = response.body()!!.response.body.totalCount - 1
for (i in 0..totalCount) {
index %= 6
when(it[i].category) {
"PTY" -> weatherArr[index].rainType = it[i].fcstValue // 강수 형태
"REH" -> weatherArr[index].humidity = it[i].fcstValue // 습도
"SKY" -> weatherArr[index].sky = it[i].fcstValue // 하늘 상태
"T1H" -> weatherArr[index].temp = it[i].fcstValue // 기온
else -> continue
}
index++
}
// 각 날짜 배열 시간 설정
for (i in 0..5) weatherArr[i].fcstTime = it[i].fcstTime
// 리사이클러 뷰에 데이터 연결
weatherRecyclerView.adapter = WeatherAdapter(weatherArr)
// 토스트 띄우기
Toast.makeText(applicationContext, it[0].fcstDate + ", " + it[0].fcstTime + "의 날씨 정보입니다.", Toast.LENGTH_SHORT).show()
}
}
// 응답 실패 시
override fun onFailure(call: Call<WEATHER>, t: Throwable) {
val tvError = findViewById<TextView>(R.id.tvError)
tvError.text = "api fail : " + t.message.toString() + "\n 다시 시도해주세요."
tvError.visibility = View.VISIBLE
Log.d("api fail", t.message.toString())
}
})
}
// baseTime 설정하기
private fun getBaseTime(h : String, m : String) : String {
var result = ""
// 45분 전이면
if (m.toInt() < 45) {
// 0시면 2330
if (h == "00") result = "2330"
// 아니면 1시간 전 날씨 정보 부르기
else {
var resultH = h.toInt() - 1
// 1자리면 0 붙여서 2자리로 만들기
if (resultH < 10) result = "0" + resultH + "30"
// 2자리면 그대로
else result = resultH.toString() + "30"
}
}
// 45분 이후면 바로 정보 받아오기
else result = h + "30"
return result
}
}
view raw MainActivity.kt hosted with ❤ by GitHub


1, WeatherInterface에서 retrofit 설정할 때 baseUrl은 공공 데이터 포탈에서 아래 주소를 복붙하면 됨

baseUrl("http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/")

 

~이제부턴 제공된 문서 참고~

 

2, 나는 이중에 "초단기 예보 조회"를 사용해서 WeatherInterface에서 @GET 부분에 getUltraSrtFcst 썼다.

 // getUltraSrtFcst : 초단기 예보 조회 + 인증키
    @GET("getUltraSrtFcst?serviceKey=서비스키_여기에_")

 

3, 데이터를 요청할 때 아래의 정보가 필요한데

이 작업은 WeatherInterface에서 이렇게 정의하고

fun GetWeather(@Query("numOfRows") num_of_rows : Int,   // 한 페이지 경과 수
                   @Query("pageNo") page_no : Int,          // 페이지 번호
                   @Query("dataType") data_type : String,   // 응답 자료 형식
                   @Query("base_date") base_date : String,  // 발표 일자
                   @Query("base_time") base_time : String,  // 발표 시각
                   @Query("nx") nx : String,                // 예보지점 X 좌표
                   @Query("ny") ny : String)                // 예보지점 Y 좌표
            : Call<WEATHER>

부르는 건 MainActivity에서 하게 했다.

// 날씨 정보 가져오기
// (한 페이지 결과 수 = 60, 페이지 번호 = 1, 응답 자료 형식-"JSON", 발표 날싸, 발표 시각, 예보지점 좌표)
val call = ApiObject.retrofitService.GetWeather(60, 1, "JSON", base_date, base_time, nx, ny)

 

 

 

4, 요청받은 데이터는 아래의 응답을 주는데,

나는 노란 밑줄친 부분만 필요해서 MainActivity에 

// xml 파일 형식을 data class로 구현
data class WEATHER (val response : RESPONSE)
data class RESPONSE(val header : HEADER, val body : BODY)
data class HEADER(val resultCode : Int, val resultMsg : String)
data class BODY(val dataType : String, val items : ITEMS, val totalCount : Int)
data class ITEMS(val item : List<ITEM>)
// category : 자료 구분 코드, fcstDate : 예측 날짜, fcstTime : 예측 시간, fcstValue : 예보 값
data class ITEM(val category : String, val fcstDate : String, val fcstTime : String, val fcstValue : String)

위와 같이 적었다.

 

 

5, 응답 메시지의 xml은 아래와 같은데

이를 data class로 표현해주기 위해 아래와 같이 표현했다.

 

response 안에 header, body가 있고...heraer 안에 resultCode와 resultMsg가 있고... 이런 식이다.

// xml 파일 형식을 data class로 구현
data class WEATHER (val response : RESPONSE)
data class RESPONSE(val header : HEADER, val body : BODY)
data class HEADER(val resultCode : Int, val resultMsg : String)
data class BODY(val dataType : String, val items : ITEMS, val totalCount : Int)
data class ITEMS(val item : List<ITEM>)
// category : 자료 구분 코드, fcstDate : 예측 날짜, fcstTime : 예측 시간, fcstValue : 예보 값
data class ITEM(val category : String, val fcstDate : String, val fcstTime : String, val fcstValue : String)

 

 

6, item의 category에는 아래의 코드값이 오는데, 나는 노란색 부분만 필요해서

이렇게 클래스를 만들어서

// 날씨 정보를 담는 데이터 클래스
class ModelWeather {
    var rainType = ""       // 강수 형태
    var humidity = ""       // 습도
    var sky = ""            // 하능 상태
    var temp = ""           // 기온
    var fcstTime = ""       // 예보시각
}

각 시간대의 날씨 정보를 배열 담았다.

// 배열 채우기
 var index = 0
 val totalCount = response.body()!!.response.body.totalCount - 1
 for (i in 0..totalCount) {
 	index %= 6
	when(it[i].category) {
 		"PTY" -> weatherArr[index].rainType = it[i].fcstValue     // 강수 형태
		"REH" -> weatherArr[index].humidity = it[i].fcstValue     // 습도
		"SKY" -> weatherArr[index].sky = it[i].fcstValue          // 하늘 상태
		"T1H" -> weatherArr[index].temp = it[i].fcstValue         // 기온
		else -> continue
		}
		index++
	}

// 각 날짜 배열 시간 설정
for (i in 0..5) weatherArr[i].fcstTime = it[i].fcstTime

index를 6의 나머지인 0~5으로 고정한 이유는 6개의 배열을 인덱스 에러 없이 채우기 위해서임

 

 

7, 아래의 정보로 강수 형태와 하늘 상태에 대한 string값을 정했다.

// 강수 형태
tvRainType.text = getRainType(item.rainType)
// 하늘 상태
tvSky.text = getSky(item.sky)
 // 강수 형태
    fun getRainType(rainType : String) : String {
        return when(rainType) {
            "0" -> "없음"
            "1" -> "비"
            "2" -> "비/눈"
            "3" -> "눈"
            else -> "오류 rainType : " + rainType
        }
    }

    // 하늘 상태
    fun getSky(sky : String) : String {
        return when(sky) {
            "1" -> "맑음"
            "3" -> "구름 많음"
            "4" -> "흐림"
            else -> "오류 rainType : " + sky
        }
    }

 

 

8, baseTime(예보자료 시각) 설정은 API 제공이 45분 이후니까

  • 45분 이전이면 1시간 전으로 baseTime 설정하기
  • 1자리면 2자리로 만들고 2자리면 시간 그대로 붙이기
  • 분은 무조건 30분

이렇게 구현했다.

// baseTime 설정하기
    private fun getBaseTime(h : String, m : String) : String {
        var result = ""

        // 45분 전이면
        if (m.toInt() < 45) {
            // 0시면 2330
            if (h == "00") result = "2330"
            // 아니면 1시간 전 날씨 정보 부르기
            else {
                var resultH = h.toInt() - 1
                // 1자리면 0 붙여서 2자리로 만들기
                if (resultH < 10) result = "0" + resultH + "30"
                // 2자리면 그대로
                else result = resultH.toString() + "30"
            }
        }
        // 45분 이후면 바로 정보 받아오기
        else result = h + "30"

        return result

그리고 현재 시각이 00시라 1시간 전이 23시라면 어제 날짜로 baseDate도 변경했다.

// 현재 시각이 00시이고 45분 이하여서 baseTime이 2330이면 어제 정보 받아오기
        if (timeH == "00" && base_time == "2330") {
            cal.add(Calendar.DATE, -1).toString()
            base_date = SimpleDateFormat("yyyyMMdd", Locale.getDefault()).format(cal.time)
        }

 

9, 참고로 기온별 옷차림 추천 참고 자료는 이거


다음에 해볼 것

  • 사용자 현재 위치 가져와서 위경도 값을 직접 좌표 값으로 변환
  • 위젯 만들기
  • 가로로 슬라이드하는 리사이클러뷰(?) 만들어보기
반응형
Comments