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.graphics.Bitmap
import android.graphics.Color
import android.location.Location
import android.net.Uri
import android.net.http.SslError
import android.os.Build
@ -157,7 +158,8 @@ internal class LauncherActivity : AppCompatActivity() {
@JvmStatic var lActivity: LauncherActivity? = null
@JvmStatic var appWidgetManager: AppWidgetManager? = null
@JvmStatic var appWidgetHost: WidgetHost? = null
fun refreshDeviceData() {
fun refreshDeviceData()
{
Executors.newSingleThreadScheduledExecutor().schedule({
mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG)
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.annotations.Ignore
class WeatherInfo : RealmObject {
constructor()
constructor(coord: Location?, weather: Array<Weather>?, main: Main?) {
this.coord = coord
weather?.let {
this.weather?.addAll(it)
}
//class WeatherInfo : RealmObject {
// constructor()
//// constructor(coord: Loc?, weather: Array<Weather>?, main: Main?) {
//// this.coord = coord
//// weather?.let {
//// 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
}
@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 {
class Loc : RealmObject {
var lon: 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.Priority
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.ext.query
import io.realm.kotlin.types.TypedRealmObject
import rasel.lunar.launcher.model.WeatherInfo
import rasel.lunar.launcher.model.WeatherForcast
import rasel.lunar.launcher.utils.BLog
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.create
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query
import kotlin.reflect.KClass
class OpenWeatherGetter(context: Context, workerParams: WorkerParameters) : BaseGetter(context, workerParams) {
companion object {
val TAG = "OpenWeatherGetter"
}
//////////////////////////////////////////
val KEY = "87cd0810b7e4b4debd31a6ef98b98154" // openWeatherMap api key
var alt: Double? = null // 경도
// openWeatherMap
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 // 위도
//////////////////////////////////////////
@SuppressLint("MissingPermission")
override fun realWork(): Result {
BLog.LOGE("${TAG} realWork() ")
// setLocation()
// 위치 위,경도 가져오자
setLocation()
fun location(loc: Location?) {
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()
}
@SuppressLint("MissingPermission")
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() {
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")
// }
// })
}
fun getWeather(loc: Location?) {
}
}
interface RestrofitService {
@GET("/data/2.5/weather")
fun getPosts(@Query("lat") lat: Double, @Query("lon") alt: Double, @Query("appid") key: String): Call<WeatherInfo?>?
// open_weather_map
// @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 rasel.lunar.launcher.apps.SimpleContact
import rasel.lunar.launcher.model.AppInfo
import rasel.lunar.launcher.model.Astro
import rasel.lunar.launcher.model.BotCommandEentitie
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.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.Main
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.TelegramMessage
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 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,
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

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>