openWeatherMap -> weatherApi

This commit is contained in:
JUNGGWAN KIM 2024-09-26 18:55:56 +09:00
parent 9349d32c7c
commit e872fe4e8a
9 changed files with 400 additions and 129 deletions

View File

@ -33,6 +33,7 @@ import android.content.pm.PackageManager
import android.content.res.Configuration import android.content.res.Configuration
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Color import android.graphics.Color
import android.location.Location
import android.net.Uri import android.net.Uri
import android.net.http.SslError import android.net.http.SslError
import android.os.Build import android.os.Build
@ -157,7 +158,8 @@ internal class LauncherActivity : AppCompatActivity() {
@JvmStatic var lActivity: LauncherActivity? = null @JvmStatic var lActivity: LauncherActivity? = null
@JvmStatic var appWidgetManager: AppWidgetManager? = null @JvmStatic var appWidgetManager: AppWidgetManager? = null
@JvmStatic var appWidgetHost: WidgetHost? = null @JvmStatic var appWidgetHost: WidgetHost? = null
fun refreshDeviceData() { fun refreshDeviceData()
{
Executors.newSingleThreadScheduledExecutor().schedule({ Executors.newSingleThreadScheduledExecutor().schedule({
mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG) mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG)
mWorkManager?.enqueueUniquePeriodicWork( mWorkManager?.enqueueUniquePeriodicWork(

View File

@ -0,0 +1,168 @@
package rasel.lunar.launcher.model
import io.realm.kotlin.ext.realmListOf
import io.realm.kotlin.types.RealmList
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.Ignore
class WeatherForcast: RealmObject {
var location: Location? = null
var current: Current? = null
var forecast: Forecast? = null
fun readyForSaving() {
forecast?.fill()
}
}
//////////////////////////////////
class Location: RealmObject {
var name: String? = null
var region: String? = null
var country: String? = null
var lat = 0.0
var lon = 0.0
var tz_id: String? = null
var localtime_epoch = 0
var localtime: String? = null
}
class Current: RealmObject {
var last_updated_epoch = 0
var last_updated: String? = null
var temp_c = 0.0
var temp_f = 0.0
var is_day = 0
var condition: Condition? = null
var wind_mph = 0.0
var wind_kph = 0.0
var wind_degree = 0
var wind_dir: String? = null
var pressure_mb = 0.0
var pressure_in = 0.0
var precip_mm = 0.0
var precip_in = 0.0
var humidity = 0
var cloud = 0
var feelslike_c = 0.0
var feelslike_f = 0.0
var windchill_c = 0.0
var windchill_f = 0.0
var heatindex_c = 0.0
var heatindex_f = 0.0
var dewpoint_c = 0.0
var dewpoint_f = 0.0
var vis_km = 0.0
var vis_miles = 0.0
var uv = 0.0
var gust_mph = 0.0
var gust_kph = 0.0
}
class Forecast: RealmObject {
@Ignore
var forecastday: ArrayList<Forecastday> = arrayListOf()
var forecastdayRealm: RealmList<Forecastday> = realmListOf()
fun fill() {
if (forecastdayRealm.addAll(forecastday)) {
forecastdayRealm.forEach { f -> f.fill() }
}
}
}
//////////////////////////////////
// Current
class Condition: RealmObject {
var text: String? = null
var icon: String? = null
var code = 0
}
// Forecast
class Forecastday: RealmObject {
var date: String? = null
var date_epoch = 0
var day: Day? = null
var astro: Astro? = null
@Ignore
var hour: ArrayList<Hour> = arrayListOf()
var hourRealm: RealmList<Hour> = realmListOf()
fun fill() {
hourRealm.addAll(hour)
}
}
//////////////////////////////////
// Forecastday
class Day: RealmObject {
var maxtemp_c = 0.0
var maxtemp_f = 0.0
var mintemp_c = 0.0
var mintemp_f = 0.0
var avgtemp_c = 0.0
var avgtemp_f = 0.0
var maxwind_mph = 0.0
var maxwind_kph = 0.0
var totalprecip_mm = 0.0
var totalprecip_in = 0.0
var totalsnow_cm = 0.0
var avgvis_km = 0.0
var avgvis_miles = 0.0
var avghumidity = 0
var daily_will_it_rain = 0
var daily_chance_of_rain = 0
var daily_will_it_snow = 0
var daily_chance_of_snow = 0
var condition: Condition? = null
var uv = 0.0
}
class Astro: RealmObject {
var sunrise: String? = null
var sunset: String? = null
var moonrise: String? = null
var moonset: String? = null
var moon_phase: String? = null
var moon_illumination = 0
var is_moon_up = 0
var is_sun_up = 0
}
class Hour: RealmObject {
var time_epoch = 0
var time: String? = null
var temp_c = 0.0
var temp_f = 0.0
var is_day = 0
var condition: Condition? = null
var wind_mph = 0.0
var wind_kph = 0.0
var wind_degree = 0
var wind_dir: String? = null
var pressure_mb = 0.0
var pressure_in = 0.0
var precip_mm = 0.0
var precip_in = 0.0
var snow_cm = 0.0
var humidity = 0
var cloud = 0
var feelslike_c = 0.0
var feelslike_f = 0.0
var windchill_c = 0.0
var windchill_f = 0.0
var heatindex_c = 0.0
var heatindex_f = 0.0
var dewpoint_c = 0.0
var dewpoint_f = 0.0
var will_it_rain = 0
var chance_of_rain = 0
var will_it_snow = 0
var chance_of_snow = 0
var vis_km = 0.0
var vis_miles = 0.0
var gust_mph = 0.0
var gust_kph = 0.0
var uv = 0.0
}

View File

@ -7,67 +7,67 @@ import io.realm.kotlin.types.RealmList
import io.realm.kotlin.types.RealmObject import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.Ignore import io.realm.kotlin.types.annotations.Ignore
class WeatherInfo : RealmObject { //class WeatherInfo : RealmObject {
constructor() // constructor()
constructor(coord: Location?, weather: Array<Weather>?, main: Main?) { //// constructor(coord: Loc?, weather: Array<Weather>?, main: Main?) {
this.coord = coord //// this.coord = coord
weather?.let { //// weather?.let {
this.weather?.addAll(it) //// this.weather?.addAll(it)
} //// }
////
//// this.main = main
//// }
//
// @SerializedName("coord")
// var coord: Loc? = null
//
// @Ignore
// @SerializedName("weather")
// var weather: ArrayList<Weather>? = arrayListOf()
//
// var weathers: RealmList<Weather> = realmListOf()
//
// @SerializedName("base")
// var base: String? = null
//
// @SerializedName("main")
// var main: Main? = null
//fun filled() {
// weather?.let {
// weathers.addAll(it)
// }
//
//}
//
// @SerializedName("visibility")
// var visibility: String? = null
//
// @SerializedName("wind")
// var wind: Wind? = null
//
// @SerializedName("clouds")
// var clouds: Clouds? = null
//
// @SerializedName("dt")
// var dt: String? = null
//
// @SerializedName("sys")
// var sys: Sys? = null
//
// @SerializedName("timezone")
// var timezone: String? = null
//
// @SerializedName("id")
// var id: String? = null
//
// @SerializedName("name")
// var name: String? = null
//
// @SerializedName("cod")
// var cod: String? = null
// }
this.main = main class Loc : RealmObject {
}
@SerializedName("coord")
var coord: Location? = null
@Ignore
@SerializedName("weather")
var weather: ArrayList<Weather>? = arrayListOf()
var weathers: RealmList<Weather> = realmListOf()
@SerializedName("base")
var base: String? = null
@SerializedName("main")
var main: Main? = null
fun filled() {
weather?.let {
weathers.addAll(it)
}
}
@SerializedName("visibility")
var visibility: String? = null
@SerializedName("wind")
var wind: Wind? = null
@SerializedName("clouds")
var clouds: Clouds? = null
@SerializedName("dt")
var dt: String? = null
@SerializedName("sys")
var sys: Sys? = null
@SerializedName("timezone")
var timezone: String? = null
@SerializedName("id")
var id: String? = null
@SerializedName("name")
var name: String? = null
@SerializedName("cod")
var cod: String? = null
}
class Location : RealmObject {
var lon: String? = null var lon: String? = null
var lat: String? = null var lat: String? = null
} }

View File

@ -7,105 +7,109 @@ import androidx.work.WorkerParameters
import com.google.android.gms.location.LocationServices import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority import com.google.android.gms.location.Priority
import com.google.android.gms.tasks.CancellationTokenSource import com.google.android.gms.tasks.CancellationTokenSource
import io.realm.kotlin.Realm
import io.realm.kotlin.RealmConfiguration
import io.realm.kotlin.UpdatePolicy import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.query import io.realm.kotlin.ext.query
import io.realm.kotlin.types.TypedRealmObject import rasel.lunar.launcher.model.WeatherForcast
import rasel.lunar.launcher.model.WeatherInfo
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.create import retrofit2.create
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.Path import retrofit2.http.Path
import retrofit2.http.Query import retrofit2.http.Query
import kotlin.reflect.KClass
class OpenWeatherGetter(context: Context, workerParams: WorkerParameters) : BaseGetter(context, workerParams) { class OpenWeatherGetter(context: Context, workerParams: WorkerParameters) : BaseGetter(context, workerParams) {
companion object { companion object {
val TAG = "OpenWeatherGetter" val TAG = "OpenWeatherGetter"
} }
////////////////////////////////////////// //////////////////////////////////////////
val KEY = "87cd0810b7e4b4debd31a6ef98b98154" // openWeatherMap api key // openWeatherMap
var alt: Double? = null // 경도 val URI_OPEN_WEATHER_MAP = "https://api.openweathermap.org"
val KEY_OPEN_WEATHER_MAP = "87cd0810b7e4b4debd31a6ef98b98154"
// weatherapi
val VER_WEATHERAPI = "v1"
val URI_WEATHERAPI = "https://api.weatherapi.com"
val KEY_WEATHERAPI = "8133d83d23ab4175a4160624241909"
val DAYS = 1
//////////////////////////////////////////
var lon: Double? = null // 경도
var lat: Double? = null // 위도 var lat: Double? = null // 위도
////////////////////////////////////////// //////////////////////////////////////////
@SuppressLint("MissingPermission")
override fun realWork(): Result { override fun realWork(): Result {
BLog.LOGE("${TAG} realWork() ") BLog.LOGE("${TAG} realWork() ")
// setLocation()
// 위치 위,경도 가져오자 fun location(loc: Location?) {
setLocation() val service = Retrofit.Builder()
.baseUrl(URI_WEATHERAPI)
.addConverterFactory(GsonConverterFactory.create())
.build()
.run { this.create<RestrofitService>() }
service.getForecast(
ver = VER_WEATHERAPI,
key = KEY_WEATHERAPI,
q = "${loc?.latitude ?: lat},${loc?.longitude ?: lon}",
days = DAYS.toString()
)?.execute()?.let { response ->
response.body()?.let { weatherInfo ->
BLog.LOGE("Location error >>> $weatherInfo")
WorkersDb.getRealm().writeBlocking {
weatherInfo.readyForSaving()
copyToRealm(weatherInfo, UpdatePolicy.ALL)
}
BLog.LOGE("saved weatherForcast >>> ${WorkersDb.getRealm().query<WeatherForcast>().first().find()}")
}
}
}
val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this.applicationContext)
fusedLocationProviderClient.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY,CancellationTokenSource().token)
.addOnSuccessListener{ success: Location? ->
success?.let {
BLog.LOGE("Location >>> $it")
BLog.LOGE("Location >>> (latitude)${it.longitude}/(longitude)${it.latitude}")
lon = it.longitude
lat = it.latitude
//{https://home.openweathermap.org/api 에서 정보를 조회 하자}
location(null)
}
}.addOnFailureListener{
BLog.LOGE("Location error >>> $it")
}
// }
return Result.success() return Result.success()
} }
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
fun setLocation() { fun setLocation() {
val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this.applicationContext)
fusedLocationProviderClient.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY,CancellationTokenSource().token)
.addOnSuccessListener{ success: Location? ->
success?.let {
BLog.LOGE("Location >>> $it")
BLog.LOGE("Location altitude >>> ${it.longitude}")
alt = it.longitude
BLog.LOGE("Location latitude >>> ${it.latitude}")
lat = it.latitude
//{https://home.openweathermap.org/api 에서 정보를 조회 하자}
getWeather()
}
}.addOnFailureListener{
BLog.LOGE("Location error >>> $it")
}
return
} }
fun getWeather() { fun getWeather(loc: Location?) {
val retro = Retrofit.Builder()
.baseUrl("https://api.openweathermap.org")
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retro.create<RestrofitService>()
BLog.LOGE("Location lat >>> ${lat}")
BLog.LOGE("Location alt >>> ${alt}")
if (lat != null && alt != null) {
val call = service.getPosts(lat!!, alt!!, KEY)
call?.execute()?.let {response ->
response.body()?.let { w ->
BLog.LOGE("Location error >>> ${w.coord}}")
WorkersDb.getRealm().writeBlocking {
w.filled().run {
copyToRealm(w, UpdatePolicy.ALL)
}
}
BLog.LOGE("db에 저장된 weatherInfo >>> ${WorkersDb.getRealm().query<WeatherInfo>().first().find()?.base}")
}
}
// call?.enqueue(object : Callback<WeatherInfo?> {
// override fun onResponse(
// call: Call<WeatherInfo?>,
// response: Response<WeatherInfo?>
// ) {
// BLog.LOGE("Location error >>> $response")
// // Realm을 이용해서 db에 저장
//
// }
//
// override fun onFailure(call: Call<WeatherInfo?>, t: Throwable) {
// BLog.LOGE("Location error >>> $t")
// }
// })
}
} }
} }
interface RestrofitService { interface RestrofitService {
@GET("/data/2.5/weather") // open_weather_map
fun getPosts(@Query("lat") lat: Double, @Query("lon") alt: Double, @Query("appid") key: String): Call<WeatherInfo?>? // @GET("/data/2.5/weather")
// fun getPosts(
// @Query("lat") lat: Double,
// @Query("lon") lon: Double,
// @Query("appid") key: String
// ): Call<WeatherInfo?>?
// weather_api
@GET("/{ver}/forecast.json")
fun getForecast(
@Path("ver") ver: String,
@Query("key") key: String,
@Query("q") q: String,
@Query("days") days: String
): Call<WeatherForcast?>?
} }

View File

@ -13,9 +13,16 @@ import io.realm.kotlin.types.annotations.Ignore
import io.realm.kotlin.types.annotations.PrimaryKey import io.realm.kotlin.types.annotations.PrimaryKey
import rasel.lunar.launcher.apps.SimpleContact import rasel.lunar.launcher.apps.SimpleContact
import rasel.lunar.launcher.model.AppInfo import rasel.lunar.launcher.model.AppInfo
import rasel.lunar.launcher.model.Astro
import rasel.lunar.launcher.model.BotCommandEentitie import rasel.lunar.launcher.model.BotCommandEentitie
import rasel.lunar.launcher.model.Clouds import rasel.lunar.launcher.model.Clouds
import rasel.lunar.launcher.model.Condition
import rasel.lunar.launcher.model.Current
import rasel.lunar.launcher.model.CurrentPlayItem import rasel.lunar.launcher.model.CurrentPlayItem
import rasel.lunar.launcher.model.Day
import rasel.lunar.launcher.model.Forecast
import rasel.lunar.launcher.model.Forecastday
import rasel.lunar.launcher.model.Hour
import rasel.lunar.launcher.model.Location import rasel.lunar.launcher.model.Location
import rasel.lunar.launcher.model.Main import rasel.lunar.launcher.model.Main
import rasel.lunar.launcher.model.NotificationItem import rasel.lunar.launcher.model.NotificationItem
@ -28,7 +35,7 @@ import rasel.lunar.launcher.model.TelegramData
import rasel.lunar.launcher.model.TelegramFrom import rasel.lunar.launcher.model.TelegramFrom
import rasel.lunar.launcher.model.TelegramMessage import rasel.lunar.launcher.model.TelegramMessage
import rasel.lunar.launcher.model.Weather import rasel.lunar.launcher.model.Weather
import rasel.lunar.launcher.model.WeatherInfo import rasel.lunar.launcher.model.WeatherForcast
import rasel.lunar.launcher.model.Wind import rasel.lunar.launcher.model.Wind
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -37,7 +44,8 @@ object WorkersDb {
val clazz : Set<KClass<out BaseRealmObject>> = setOf(RssData::class, NotificationItem::class, AppInfo::class,SimpleContact::class, RecentCall::class, RecentSms::class, CurrentPlayItem::class, val clazz : Set<KClass<out BaseRealmObject>> = setOf(RssData::class, NotificationItem::class, AppInfo::class,SimpleContact::class, RecentCall::class, RecentSms::class, CurrentPlayItem::class,
TelegramBotUpdate::class, TelegramData::class, TelegramMessage::class, TelegramChat::class, BotCommandEentitie::class, TelegramFrom::class, WeatherInfo::class, Main::class, Weather::class, Location::class, Wind::class, Clouds::class, Sys::class TelegramBotUpdate::class, TelegramData::class, TelegramMessage::class, TelegramChat::class, BotCommandEentitie::class, TelegramFrom::class,
WeatherForcast::class, Location::class, Current::class, Forecast::class, Condition::class, Forecastday::class, Day::class, Astro::class, Hour::class
) )
val schemaVersion : Long = 0L val schemaVersion : Long = 0L

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
</selector>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="80dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="오후"
android:gravity="center"
android:fontFamily="sans-serif-medium"
android:textSize="14sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="16시"
android:fontFamily="sans-serif-medium"
android:gravity="center"
android:textSize="14sp"
android:textAlignment="center"/>
<ImageView
android:id="@+id/imageView2"
android:layout_width="40dp"
android:layout_height="40dp"
android:contentDescription="시계 아이콘"
app:srcCompat="@drawable/ico_time" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="27도"
android:fontFamily="sans-serif-medium"
android:textSize="14sp"
android:gravity="center"
android:textAlignment="center"/>
</LinearLayout>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:textAlignment="center">
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="409dp"
android:layout_height="wrap_content"
android:gravity="left|center"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="25dp"
android:layout_height="25dp"
android:contentDescription="시계 아이콘"
app:srcCompat="@drawable/ico_time"
tools:ignore="ImageContrastCheck"
android:layout_marginLeft="20dp"/>
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:text="시간별 예보"
android:textAlignment="center"
android:textSize="14sp"
android:layout_marginLeft="10dp"/>
</LinearLayout>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/linearLayout"
app:layout_constraintLeft_toLeftOf="@id/linearLayout"
app:layout_constraintRight_toRightOf="@id/linearLayout">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
</HorizontalScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>