This commit is contained in:
lunaticbum 2024-10-08 15:59:51 +09:00
commit dd92a39f16
14 changed files with 154 additions and 68 deletions

View File

@ -204,6 +204,11 @@ internal class LauncherActivity : AppCompatActivity() {
}, 5, TimeUnit.SECONDS) }, 5, TimeUnit.SECONDS)
} }
fun doGetWheaterByLocationInfo() {
Executors.newSingleThreadScheduledExecutor().schedule({
mWorkManager?.enqueue(OneTimeWorkRequest.from(OpenWeatherGetter::class.java))
}, 5, TimeUnit.SECONDS)
}
fun refreshFeeds() { fun refreshFeeds() {
var delay = 5L var delay = 5L
@ -308,17 +313,19 @@ internal class LauncherActivity : AppCompatActivity() {
.addTag(LocationGetter.TAG) .addTag(LocationGetter.TAG)
.build()) .build())
}, weatherDelay, TimeUnit.SECONDS) }, weatherDelay, TimeUnit.SECONDS)
Executors.newSingleThreadScheduledExecutor().schedule({
//de574a260b1f474d99955729241909 // Executors.newSingleThreadScheduledExecutor().schedule({
mWorkManager?.cancelAllWorkByTag(OpenWeatherGetter.TAG) // //de574a260b1f474d99955729241909
mWorkManager?.enqueueUniquePeriodicWork( // mWorkManager?.cancelAllWorkByTag(OpenWeatherGetter.TAG)
OpenWeatherGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, // mWorkManager?.enqueueUniquePeriodicWork(
PeriodicWorkRequestBuilder<OpenWeatherGetter>(midTimePeriod, TimeUnit.MINUTES) // OpenWeatherGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
.addTag(OpenWeatherGetter.TAG) // PeriodicWorkRequestBuilder<OpenWeatherGetter>(midTimePeriod, TimeUnit.MINUTES)
.build()) // .addTag(OpenWeatherGetter.TAG)
}, weatherDelay + 3, TimeUnit.SECONDS) // .build())
// }, weatherDelay + 3, TimeUnit.SECONDS)
} }
fun workmanager() : WorkManager? { fun workmanager() : WorkManager? {
if (mWorkManager == null && lActivity != null) { if (mWorkManager == null && lActivity != null) {
mWorkManager = WorkManager.getInstance(lActivity!!) mWorkManager = WorkManager.getInstance(lActivity!!)

View File

@ -53,6 +53,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.work.OneTimeWorkRequest import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager import androidx.work.WorkManager
import io.realm.kotlin.Realm
import io.realm.kotlin.ext.asFlow import io.realm.kotlin.ext.asFlow
import io.realm.kotlin.ext.query import io.realm.kotlin.ext.query
import io.realm.kotlin.notifications.InitialObject import io.realm.kotlin.notifications.InitialObject
@ -61,12 +62,14 @@ import io.realm.kotlin.notifications.ObjectChange
import io.realm.kotlin.notifications.ResultsChange import io.realm.kotlin.notifications.ResultsChange
import io.realm.kotlin.notifications.UpdatedObject import io.realm.kotlin.notifications.UpdatedObject
import io.realm.kotlin.notifications.UpdatedResults import io.realm.kotlin.notifications.UpdatedResults
import io.realm.kotlin.query.RealmQuery
import io.realm.kotlin.query.RealmResults import io.realm.kotlin.query.RealmResults
import io.realm.kotlin.query.Sort import io.realm.kotlin.query.Sort
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.ConnectionPool import okhttp3.ConnectionPool
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -93,6 +96,7 @@ import rasel.lunar.launcher.home.adapters.SmsLogsAdapter
import rasel.lunar.launcher.home.adapters.WeatherAdapter import rasel.lunar.launcher.home.adapters.WeatherAdapter
import rasel.lunar.launcher.model.CurrentPlayItem import rasel.lunar.launcher.model.CurrentPlayItem
import rasel.lunar.launcher.model.Hour import rasel.lunar.launcher.model.Hour
import rasel.lunar.launcher.model.Location
import rasel.lunar.launcher.model.NotificationItem import rasel.lunar.launcher.model.NotificationItem
import rasel.lunar.launcher.model.RssData import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.RssDataInterface import rasel.lunar.launcher.model.RssDataInterface
@ -106,10 +110,13 @@ import rasel.lunar.launcher.utils.JamoUtils
import rasel.lunar.launcher.utils.SimpleFingerGestures import rasel.lunar.launcher.utils.SimpleFingerGestures
import rasel.lunar.launcher.utils.beforeDay import rasel.lunar.launcher.utils.beforeDay
import rasel.lunar.launcher.view.TableRadioGroup import rasel.lunar.launcher.view.TableRadioGroup
import rasel.lunar.launcher.workers.LocationGetter
import rasel.lunar.launcher.workers.OpenWeatherGetter
import rasel.lunar.launcher.workers.RecentCall import rasel.lunar.launcher.workers.RecentCall
import rasel.lunar.launcher.workers.RecentSms import rasel.lunar.launcher.workers.RecentSms
import rasel.lunar.launcher.workers.TelegramBotGetter import rasel.lunar.launcher.workers.TelegramBotGetter
import rasel.lunar.launcher.workers.WorkersDb import rasel.lunar.launcher.workers.WorkersDb
import java.math.BigDecimal
import java.net.URLEncoder import java.net.URLEncoder
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
@ -294,43 +301,62 @@ internal class LauncherHome : Fragment() {
} }
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun queryWeather() { suspend fun queryWeatherWithLoc(){
mWeatherResult = WorkersDb.getRealm().query<WeatherForcast>().find() WorkersDb.getRealm()
val weatherJob = CoroutineScope(Dispatchers.Default).launch { .query<Hour>()
mWeatherResult?.asFlow()?.collect { changes -> .query("lat == $0 AND lon == $1",
BLog.LOGE("saved weatherForcast >>> asFlow ${changes.list}") LocationGetter.latitude?.let { BigDecimal.valueOf(it).toDouble() },
if (changes.list.size > 0) { LocationGetter.longitude?.let { BigDecimal.valueOf(it).toDouble() }
changes.list.first().forecast?.forecastdayRealm?.let { li -> ).also {
BLog.LOGE("LauncherHome Saved Forecastdays >>> ${li.size}") BLog.LOGE("re >>> ${it.description()}")
Handler(Looper.getMainLooper()).post { }.find().let {hours ->
mWeatherAdapter?.let{ Handler(Looper.getMainLooper()).post {
it.update( mWeatherAdapter?.let {
mutableListOf<Hour>().apply { it.update(
li.forEach { i -> mutableListOf<Hour>().apply {
if (i == li.first()) { this.addAll(it.filter(hours))
this.addAll(it }
.filter( )
i.hourRealm.also { hli -> it.notifyDataSetChanged()
BLog.LOGE("LauncherHome Saved hli size >>> ${hli.size}")
}
).also { fli ->
BLog.LOGE("LauncherHome Saved fli size >>> ${fli.size}")
}
)
} else {
this.addAll(i.hourRealm)
}
}
}
)
it.notifyDataSetChanged()
}
} }
} }
}
// .asFlow()
// .collect { changes ->
// if (changes.list.size > 0) {
// Handler(Looper.getMainLooper()).post {
// mWeatherAdapter?.let {
// it.update(
// mutableListOf<Hour>().apply {
// this.addAll(it.filter(changes.list))
// }
// )
// it.notifyDataSetChanged()
// }
// }
// }
// }
}
var weatherJob : Job? = null
var result : RealmResults<WeatherForcast>? = null
// lateinit var weatherJob : Job
// @SuppressLint("NotifyDataSetChanged")
private fun queryWeather() {
result = WorkersDb.getRealm().query<WeatherForcast>().also {
BLog.LOGE("re >>> ${it.description()}") // 쿼리 로그
}.find()
weatherJob?.cancel()
weatherJob = CoroutineScope(Dispatchers.Default).launch {
result?.asFlow()?.collect { li ->
BLog.LOGE("queryWeather done. >>> ${li}")
if (li.list.size > 0) {
BLog.LOGE("queryWeather done. >>> ${li.list.size}")
queryWeatherWithLoc()
} }
} }
} }
weatherJob.start() weatherJob?.start()
} }
val hideListViewTime = 1000L * 60L * 15L val hideListViewTime = 1000L * 60L * 15L

View File

@ -2,26 +2,24 @@ package rasel.lunar.launcher.home.adapters
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.graphics.Color import android.graphics.Color
import android.support.annotation.ColorInt
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.realm.kotlin.ext.toRealmList
import rasel.lunar.launcher.R import rasel.lunar.launcher.R
import rasel.lunar.launcher.home.adapters.WeatherAdapter.ViewHolder import rasel.lunar.launcher.home.adapters.WeatherAdapter.ViewHolder
import rasel.lunar.launcher.model.Forecastday import rasel.lunar.launcher.model.Day
import rasel.lunar.launcher.model.Hour import rasel.lunar.launcher.model.Hour
import rasel.lunar.launcher.model.WeatherForcast
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import java.time.Instant import java.time.Instant
import java.time.ZoneId import java.time.ZoneId
import java.util.Calendar
import java.util.Date
class WeatherAdapter(private val dataSet: ArrayList<Hour>): RecyclerView.Adapter<ViewHolder>(){ class WeatherAdapter(private val dataSet: ArrayList<Hour>): RecyclerView.Adapter<ViewHolder>(){
var isChangedAmOrPm: Boolean = true var isChangedAmOrPm: Boolean = true
var day: Int = 0
class ViewHolder(view: View): RecyclerView.ViewHolder(view) { class ViewHolder(view: View): RecyclerView.ViewHolder(view) {
val viewItem: View val viewItem: View
@ -54,10 +52,15 @@ class WeatherAdapter(private val dataSet: ArrayList<Hour>): RecyclerView.Adapter
return ViewHolder(view) return ViewHolder(view)
} }
fun getToday() = Calendar.getInstance().get(Calendar.DAY_OF_YEAR)
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val data = dataSet[position] as? Hour val data = dataSet[position] as? Hour
BLog.LOGE("saved weatherForcast >>> asFlow ${dataSet.size}") BLog.LOGE("saved weatherForcast >>> asFlow ${dataSet.size}")
// val today = Calendar.getInstance()
// today.time = Date(data?.time_epoch?.toLong()?.times(1000L) ?: 0L)
// val dayOfItem = today.get(Calendar.DAY_OF_YEAR)
data?.let { data?.let {
holder.viewItem.findViewById<TextView>(R.id.amOrPm) holder.viewItem.findViewById<TextView>(R.id.amOrPm)
.apply { .apply {
@ -75,14 +78,13 @@ class WeatherAdapter(private val dataSet: ArrayList<Hour>): RecyclerView.Adapter
} }
holder.viewItem.findViewById<TextView>(R.id.hour) holder.viewItem.findViewById<TextView>(R.id.hour)
.apply { .apply {
this.isSelected = (System.currentTimeMillis() % 3 == 0L)
Instant.ofEpochSecond(it.time_epoch.toLong()) Instant.ofEpochSecond(it.time_epoch.toLong())
.atZone(ZoneId.systemDefault()) .atZone(ZoneId.systemDefault())
.run { .run {
if (this.hour == 0) { if (this.hour == 0) {
this@apply.setTextColor(Color.BLACK) this@apply.setTextColor(Color.BLACK)
this@apply.isSelected = true this@apply.isSelected = true
this@apply.text = when (day++) { this@apply.text = when (this.dayOfYear - getToday()) {
1 -> "내일" 1 -> "내일"
2 -> "모레" 2 -> "모레"
3 -> "글피" 3 -> "글피"
@ -94,13 +96,34 @@ class WeatherAdapter(private val dataSet: ArrayList<Hour>): RecyclerView.Adapter
this@apply.text = "${this.hour}" this@apply.text = "${this.hour}"
} }
} }
holder.viewItem.findViewById<ImageView>(R.id.imgDress)
.run { this.setImageResource(R.drawable.ico_time) }
holder.viewItem.findViewById<TextView>(R.id.temperature)
.run {
this.text = "${it.temp_c}"
}
} }
var img: Int? = null
var textDress: String? = null
if (it.temp_c >= 23) {
img = R.drawable.dress_short_sleeves
textDress = "반팔"
} else if ((23 > it.temp_c) && (it.temp_c >= 20)) {
img = R.drawable.dress_long_sleeves
textDress = "긴팔"
} else if ((20 > it.temp_c) && (it.temp_c >= 17)) {
img = R.drawable.dress_knitwear
textDress = "니트"
} else if ((17 > it.temp_c) && (it.temp_c >= 12)) {
img = R.drawable.dress_flimsy_outer
textDress = "얇은겉옷"
} else if ((12 > it.temp_c) && (it.temp_c >= 6)) {
img = R.drawable.dress_heavy_outer
textDress = "두꺼운겉옷"
} else {
img = R.drawable.dress_padded_coat
textDress = "패딩"
}
holder.viewItem.findViewById<ImageView>(R.id.imgDress)
.setImageResource(img ?: R.drawable.dress_padded_coat)
holder.viewItem.findViewById<TextView>(R.id.textDress)
.text = textDress
holder.viewItem.findViewById<TextView>(R.id.temperature)
.text = "${it.temp_c}"
} }
} }

View File

@ -8,11 +8,16 @@ import io.realm.kotlin.types.annotations.PrimaryKey
class WeatherForcast: RealmObject { class WeatherForcast: RealmObject {
@PrimaryKey
var isOnlyKey = "isOnlyKey"
var location: Location? = null var location: Location? = null
var current: Current? = null var current: Current? = null
var forecast: Forecast? = null var forecast: Forecast? = null
var lastUpdateTime : Long = 0L
fun readyForSaving() { fun readyForSaving() {
lastUpdateTime = System.currentTimeMillis()
forecast?.fill() forecast?.fill()
} }
} }
@ -133,6 +138,9 @@ class Astro: RealmObject {
} }
class Hour: RealmObject { class Hour: RealmObject {
var lat : Double = 0.0
var lon : Double = 0.0
@PrimaryKey @PrimaryKey
var time_epoch = 0 var time_epoch = 0
var time: String? = null var time: String? = null

View File

@ -7,6 +7,7 @@ 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 rasel.lunar.launcher.LauncherActivity.Companion.doGetWheaterByLocationInfo
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
class LocationGetter(context: Context, workerParams: WorkerParameters) : BaseGetter(context, workerParams) { class LocationGetter(context: Context, workerParams: WorkerParameters) : BaseGetter(context, workerParams) {
@ -28,6 +29,7 @@ class LocationGetter(context: Context, workerParams: WorkerParameters) : BaseGet
BLog.LOGE("Location >>> (latitude)${it.longitude}/(longitude)${it.latitude}") BLog.LOGE("Location >>> (latitude)${it.longitude}/(longitude)${it.latitude}")
longitude = it.longitude longitude = it.longitude
latitude = it.latitude latitude = it.latitude
doGetWheaterByLocationInfo()
} }
}.addOnFailureListener{ }.addOnFailureListener{
BLog.LOGE("Location error >>> $it") BLog.LOGE("Location error >>> $it")

View File

@ -8,7 +8,9 @@ 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.UpdatePolicy import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.asFlow
import io.realm.kotlin.ext.query import io.realm.kotlin.ext.query
import rasel.lunar.launcher.model.Hour
import rasel.lunar.launcher.model.WeatherForcast import rasel.lunar.launcher.model.WeatherForcast
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import retrofit2.Call import retrofit2.Call
@ -22,16 +24,17 @@ import retrofit2.http.Query
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"
var lon: Double? = null // 경도
var lat: Double? = null // 위도
} }
////////////////////////////////////////// //////////////////////////////////////////
// weatherapi // weatherapi
val VER_WEATHERAPI = "v1" val VER_WEATHERAPI = "v1"
val URI_WEATHERAPI = "https://api.weatherapi.com" val URI_WEATHERAPI = "https://api.weatherapi.com"
val KEY_WEATHERAPI = "8133d83d23ab4175a4160624241909" val KEY_WEATHERAPI = "8133d83d23ab4175a4160624241909"
val DAYS = 2 val DAYS = 3
////////////////////////////////////////// //////////////////////////////////////////
var lon: Double? = null // 경도
var lat: Double? = null // 위도
////////////////////////////////////////// //////////////////////////////////////////
override fun realWork(): Result { override fun realWork(): Result {
@ -48,6 +51,8 @@ class OpenWeatherGetter(context: Context, workerParams: WorkerParameters) : Base
} }
fun getWeather(latitude: Double, longitude: Double) { fun getWeather(latitude: Double, longitude: Double) {
BLog.LOGE("into getWeather")
///saved weatherForcast
Retrofit.Builder() Retrofit.Builder()
.baseUrl(URI_WEATHERAPI) .baseUrl(URI_WEATHERAPI)
.addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create())
@ -57,16 +62,26 @@ class OpenWeatherGetter(context: Context, workerParams: WorkerParameters) : Base
ver = VER_WEATHERAPI, ver = VER_WEATHERAPI,
key = KEY_WEATHERAPI, key = KEY_WEATHERAPI,
q = "$latitude,$longitude", q = "$latitude,$longitude",
days = DAYS.toString() days = (System.currentTimeMillis() % 5L).toInt().toString()
)?.execute()?.let { response -> )?.execute()?.let { response ->
BLog.LOGE("into getWeather afterc excute")
BLog.LOGE("weatherApi forecast response >>> $response") BLog.LOGE("weatherApi forecast response >>> $response")
response.body()?.let { weatherInfo -> response.body()?.let { weatherInfo ->
BLog.LOGE("into getWeather on body ")
weatherInfo.readyForSaving()
weatherInfo.forecast?.forecastdayRealm?.forEach {
it.hourRealm.forEach {h ->
h.lat = lat ?: 0.0
h.lon = lon ?: 0.0
}
}
// Realm에 저장 // Realm에 저장
WorkersDb.getRealm().writeBlocking { WorkersDb.getRealm().writeBlocking {
weatherInfo.readyForSaving() var result = copyToRealm(weatherInfo, UpdatePolicy.ALL)
copyToRealm(weatherInfo, UpdatePolicy.ALL) BLog.LOGE("saved weatherForcast >>> ${result}")
} }
BLog.LOGE("saved weatherForcast >>> ${WorkersDb.getRealm().query<WeatherForcast>().first().find()}") BLog.LOGE("saved weatherForcast >>> ${WorkersDb.getRealm().query<Hour>().count().find()}")
BLog.LOGE("saved weatherForcast >>> ${WorkersDb.getRealm().query<WeatherForcast>().first().find()?.forecast?.forecastdayRealm?.size}")
} }
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

View File

@ -10,7 +10,6 @@
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="오후"
android:id="@+id/amOrPm" android:id="@+id/amOrPm"
android:gravity="center" android:gravity="center"
android:fontFamily="sans-serif-medium" android:fontFamily="sans-serif-medium"
@ -18,7 +17,6 @@
<TextView <TextView
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="16시"
android:id="@+id/hour" android:id="@+id/hour"
android:background="@drawable/date_bg" android:background="@drawable/date_bg"
android:fontFamily="sans-serif-medium" android:fontFamily="sans-serif-medium"
@ -29,16 +27,22 @@
android:id="@+id/imgDress" android:id="@+id/imgDress"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="40dp" android:layout_height="40dp"
android:contentDescription="시계 아이콘" android:contentDescription="온도별 옷차림"
app:srcCompat="@drawable/ico_time" /> app:tint="@android:color/white"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textDress"
android:fontFamily="sans-serif-light"
android:textSize="11sp"
android:gravity="center"
android:textAlignment="center"/>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="27도"
android:id="@+id/temperature" android:id="@+id/temperature"
android:fontFamily="sans-serif-medium" android:fontFamily="sans-serif-medium"
android:textSize="14sp" android:textSize="14sp"
android:gravity="center" android:gravity="center"
android:textAlignment="center"/> android:textAlignment="center"/>
</LinearLayout> </LinearLayout>

View File

@ -21,7 +21,8 @@
android:contentDescription="시계 아이콘" android:contentDescription="시계 아이콘"
app:srcCompat="@drawable/ico_time" app:srcCompat="@drawable/ico_time"
tools:ignore="ImageContrastCheck" tools:ignore="ImageContrastCheck"
android:layout_marginLeft="20dp"/> android:layout_marginLeft="20dp"
app:tint="@android:color/white" />
<TextView <TextView
android:id="@+id/textView2" android:id="@+id/textView2"
android:layout_width="wrap_content" android:layout_width="wrap_content"