From 60519240d5b888b114a5d872b9c59ce434b08a81 Mon Sep 17 00:00:00 2001 From: sohyun127 Date: Tue, 14 Nov 2023 17:02:42 +0900 Subject: [PATCH] [FEAT] : Weather api --- app/build.gradle.kts | 32 +++++++++++---- app/src/main/AndroidManifest.xml | 2 +- .../gdsc/bottomnavigation/FirstFragment.kt | 12 ++++++ .../gdsc/bottomnavigation/WeatherViewModel.kt | 29 ++++++++++++++ .../java/com/example/gdsc/data/ServicePool.kt | 25 ++++++++++-- .../example/gdsc/data/api/MemberApiService.kt | 2 + .../gdsc/data/api/WeatherApiService.kt | 35 ++++++++++++++++ .../com/example/gdsc/data/dto/BaseResponse.kt | 27 +++++++++++++ .../gdsc/data/dto/ResponseWeatherDto.kt | 40 +++++++++++++++++++ 9 files changed, 192 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/com/example/gdsc/bottomnavigation/WeatherViewModel.kt create mode 100644 app/src/main/java/com/example/gdsc/data/api/WeatherApiService.kt create mode 100644 app/src/main/java/com/example/gdsc/data/dto/BaseResponse.kt create mode 100644 app/src/main/java/com/example/gdsc/data/dto/ResponseWeatherDto.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 19865ac..28732ef 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,7 +1,9 @@ +import java.util.Properties + plugins { id("com.android.application") id("org.jetbrains.kotlin.android") - id ("org.jetbrains.kotlin.plugin.serialization") version "1.9.0" + id("org.jetbrains.kotlin.plugin.serialization") version "1.9.0" id("com.google.gms.google-services") } @@ -15,17 +17,30 @@ android { targetSdk = 33 versionCode = 1 versionName = "1.0" - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildTypes { + debug { + buildConfigField("String", "BASE_URL", Properties().apply { + load(project.rootProject.file("local.properties").inputStream()) + }["base.url"].toString()) + buildConfigField("String", "SERVICE_KEY", Properties().apply { + load(project.rootProject.file("local.properties").inputStream()) + }["service.key"].toString()) + } release { isMinifyEnabled = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) + buildConfigField("String", "BASE_URL", Properties().apply { + load(project.rootProject.file("local.properties").inputStream()) + }["base.url"].toString()) + buildConfigField("String", "SERVICE_KEY", Properties().apply { + load(project.rootProject.file("local.properties").inputStream()) + }["service.key"].toString()) } } compileOptions { @@ -35,9 +50,10 @@ android { kotlinOptions { jvmTarget = "1.8" } - buildFeatures{ + buildFeatures { dataBinding = true viewBinding = true + buildConfig = true } } @@ -54,8 +70,8 @@ dependencies { implementation("io.coil-kt:coil-compose:2.4.0") //viewModel implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2") - implementation ("androidx.fragment:fragment-ktx:1.6.1") - implementation ("androidx.activity:activity-ktx:1.7.2") + implementation("androidx.fragment:fragment-ktx:1.6.1") + implementation("androidx.activity:activity-ktx:1.7.2") //jetpack navigation implementation("androidx.navigation:navigation-fragment-ktx:2.5.3") @@ -67,9 +83,9 @@ dependencies { implementation("com.google.firebase:firebase-analytics-ktx") //retrofit - implementation ("com.squareup.retrofit2:retrofit:2.9.0") - implementation ("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1") - implementation ("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0") + implementation("com.squareup.retrofit2:retrofit:2.9.0") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1") + implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0") implementation(platform("com.squareup.okhttp3:okhttp-bom:4.10.0")) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 17ce0fc..8e841c3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,7 +15,7 @@ android:theme="@style/Theme.GDSC" tools:targetApi="31"> diff --git a/app/src/main/java/com/example/gdsc/bottomnavigation/FirstFragment.kt b/app/src/main/java/com/example/gdsc/bottomnavigation/FirstFragment.kt index 2c277ff..ad32fd1 100644 --- a/app/src/main/java/com/example/gdsc/bottomnavigation/FirstFragment.kt +++ b/app/src/main/java/com/example/gdsc/bottomnavigation/FirstFragment.kt @@ -1,13 +1,18 @@ package com.example.gdsc.bottomnavigation import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels import com.example.gdsc.databinding.FragmentFirstBinding class FirstFragment : Fragment() { + + private val viewModel by viewModels() + private var _binding: FragmentFirstBinding? = null private val binding: FragmentFirstBinding get() = requireNotNull(_binding) { " _binding이 nul이다 " } @@ -23,10 +28,17 @@ class FirstFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + observe() } override fun onDestroy() { _binding = null super.onDestroy() } + + private fun observe() { + viewModel.getWeather.observe(viewLifecycleOwner) { response -> + Log.d("testtest", response.toString()) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/gdsc/bottomnavigation/WeatherViewModel.kt b/app/src/main/java/com/example/gdsc/bottomnavigation/WeatherViewModel.kt new file mode 100644 index 0000000..c72a011 --- /dev/null +++ b/app/src/main/java/com/example/gdsc/bottomnavigation/WeatherViewModel.kt @@ -0,0 +1,29 @@ +package com.example.gdsc.bottomnavigation + +import android.util.Log +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.gdsc.data.ServicePool +import com.example.gdsc.data.dto.ResponseWeatherDto +import kotlinx.coroutines.launch + +class WeatherViewModel : ViewModel() { + private val _getWeather: MutableLiveData = MutableLiveData() + val getWeather: MutableLiveData = _getWeather + + init { + getWeather() + } + + private fun getWeather() = viewModelScope.launch { + runCatching { + ServicePool.getWeather.getWeather() + }.fold({ + _getWeather.value = it.response.body + }, { + Log.d("error", it.message.toString()) + }) + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/gdsc/data/ServicePool.kt b/app/src/main/java/com/example/gdsc/data/ServicePool.kt index d190da1..af39243 100644 --- a/app/src/main/java/com/example/gdsc/data/ServicePool.kt +++ b/app/src/main/java/com/example/gdsc/data/ServicePool.kt @@ -1,23 +1,42 @@ package com.example.gdsc.data +import android.util.Log +import com.example.gdsc.BuildConfig.BASE_URL import com.example.gdsc.data.api.MemberApiService +import com.example.gdsc.data.api.WeatherApiService import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import kotlinx.serialization.json.Json +import okhttp3.Interceptor import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit object ApiFactory { - private const val BASE_URL = - "https://gdsc-4f545-default-rtdb.asia-southeast1.firebasedatabase.app/" + private fun getLogOkHttpClient(): Interceptor { + val loggingInterceptor = HttpLoggingInterceptor { message -> + Log.d("Retrofit2", "CONNECTION INFO -> $message") + } + loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY + return loggingInterceptor + } + + private val okHttpClient = OkHttpClient.Builder() + .addInterceptor(getLogOkHttpClient()) + .build() val retrofit: Retrofit by lazy { Retrofit.Builder() .baseUrl(BASE_URL) + .client(okHttpClient) .addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) .build() } + + inline fun create(): T = retrofit.create(T::class.java) } object ServicePool { - val getMember = ApiFactory.retrofit.create(MemberApiService::class.java) + val getMember = ApiFactory.create() + val getWeather = ApiFactory.create() } \ No newline at end of file diff --git a/app/src/main/java/com/example/gdsc/data/api/MemberApiService.kt b/app/src/main/java/com/example/gdsc/data/api/MemberApiService.kt index b5ae96e..0ee0eb1 100644 --- a/app/src/main/java/com/example/gdsc/data/api/MemberApiService.kt +++ b/app/src/main/java/com/example/gdsc/data/api/MemberApiService.kt @@ -7,4 +7,6 @@ import retrofit2.http.GET interface MemberApiService { @GET("member.json") fun getMember(): Call> + + } \ No newline at end of file diff --git a/app/src/main/java/com/example/gdsc/data/api/WeatherApiService.kt b/app/src/main/java/com/example/gdsc/data/api/WeatherApiService.kt new file mode 100644 index 0000000..4f78d23 --- /dev/null +++ b/app/src/main/java/com/example/gdsc/data/api/WeatherApiService.kt @@ -0,0 +1,35 @@ +package com.example.gdsc.data.api + +import com.example.gdsc.BuildConfig.SERVICE_KEY +import com.example.gdsc.data.dto.BaseResponse +import com.example.gdsc.data.dto.ResponseWeatherDto +import retrofit2.http.GET +import retrofit2.http.Query + +interface WeatherApiService { + + companion object { + const val GET_ULTRA_SRT_NCST = "getUltraSrtNcst" + const val SERVICE_KEY_LABEL = "serviceKey" + const val NUM_OF_ROWS = "numOfRows" + const val PAGE_NO = "pageNo" + const val DATA_TYPE = "dataType" + const val BASE_DATE = "base_date" + const val BASE_TIME = "base_time" + const val NX = "nx" + const val NY = "ny" + } + + @GET(GET_ULTRA_SRT_NCST) + suspend fun getWeather( + @Query(SERVICE_KEY_LABEL) serviceKey: String = SERVICE_KEY, + @Query(NUM_OF_ROWS) numOfRows: Int = 1, + @Query(PAGE_NO) pageNo: Int = 1, + @Query(DATA_TYPE) dataType: String = "JSON", + @Query(BASE_DATE) baseDate: String = "20231114", + @Query(BASE_TIME) baseTime: String = "0600", + @Query(NX) nx: Int = 55, + @Query(NY) ny: Int = 127, + ): BaseResponse +} + diff --git a/app/src/main/java/com/example/gdsc/data/dto/BaseResponse.kt b/app/src/main/java/com/example/gdsc/data/dto/BaseResponse.kt new file mode 100644 index 0000000..36f22f2 --- /dev/null +++ b/app/src/main/java/com/example/gdsc/data/dto/BaseResponse.kt @@ -0,0 +1,27 @@ +package com.example.gdsc.data.dto + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class BaseResponse( + @SerialName("response") + val response: Response +) { + + @Serializable + data class Response( + @SerialName("header") + val header: Header, + @SerialName("body") + val body: T? = null + ) + + @Serializable + data class Header( + @SerialName("resultCode") + val resultCode: String, + @SerialName("resultMsg") + val resultMsg: String + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/gdsc/data/dto/ResponseWeatherDto.kt b/app/src/main/java/com/example/gdsc/data/dto/ResponseWeatherDto.kt new file mode 100644 index 0000000..9ed2e63 --- /dev/null +++ b/app/src/main/java/com/example/gdsc/data/dto/ResponseWeatherDto.kt @@ -0,0 +1,40 @@ +package com.example.gdsc.data.dto + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ResponseWeatherDto( + @SerialName("dataType") + val dataType: String, + @SerialName("items") + val items: Items, + @SerialName("numOfRows") + val numOfRows: Int, + @SerialName("pageNo") + val pageNo: Int, + @SerialName("totalCount") + val totalCount: Int +) { + @Serializable + data class Items( + @SerialName("item") + val item: List + ) { + @Serializable + data class Item( + @SerialName("baseDate") + val baseDate: String, + @SerialName("baseTime") + val baseTime: String, + @SerialName("category") + val category: String, + @SerialName("nx") + val nx: Int, + @SerialName("ny") + val ny: Int, + @SerialName("obsrValue") + val obsrValue: String + ) + } +} \ No newline at end of file