Fix: Fixed error with fetchWeatherData not finding url.
Signed-off-by: HeCodes2Much <wayne6324@gmail.com>
This commit is contained in:
@@ -26,10 +26,9 @@ import com.github.droidworksstudio.launcher.accessibility.ActionService
|
|||||||
import com.github.droidworksstudio.launcher.helper.weather.WeatherResponse
|
import com.github.droidworksstudio.launcher.helper.weather.WeatherResponse
|
||||||
import com.github.droidworksstudio.launcher.utils.WeatherApiService
|
import com.github.droidworksstudio.launcher.utils.WeatherApiService
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
import java.net.UnknownHostException
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -252,43 +251,52 @@ class AppHelper @Inject constructor() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchWeatherData(
|
sealed class WeatherResult {
|
||||||
|
data class Success(val weatherResponse: WeatherResponse) : WeatherResult()
|
||||||
|
data class Failure(val errorMessage: String) : WeatherResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fetchWeatherData(
|
||||||
context: Context,
|
context: Context,
|
||||||
latitude: Float,
|
latitude: Float,
|
||||||
longitude: Float
|
longitude: Float
|
||||||
): WeatherResponse {
|
): WeatherResult {
|
||||||
// Check if cached data is available and not expired
|
// Check if cached data is available and not expired
|
||||||
val cachedWeatherData = context.getWeatherDataFromCache()
|
val cachedWeatherData = context.getWeatherDataFromCache()
|
||||||
if (cachedWeatherData?.let { System.currentTimeMillis() - it.timestamp < TimeUnit.MINUTES.toMillis(15) } == true) {
|
if (cachedWeatherData?.let { System.currentTimeMillis() - it.timestamp < TimeUnit.MINUTES.toMillis(15) } == true) {
|
||||||
return cachedWeatherData.weatherResponse
|
return WeatherResult.Success(cachedWeatherData.weatherResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Fetch weather data from the network
|
// Fetch weather data from the network
|
||||||
val apiKey = BuildConfig.API_KEY
|
val apiKey = BuildConfig.API_KEY
|
||||||
|
val baseURL = "api.openweathermap.org"
|
||||||
val units = "metric"
|
val units = "metric"
|
||||||
|
|
||||||
val retrofit = Retrofit.Builder()
|
try {
|
||||||
.baseUrl("https://api.openweathermap.org/data/2.5/")
|
val retrofit = Retrofit.Builder()
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
.baseUrl("https://$baseURL/data/2.5/")
|
||||||
.build()
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build()
|
||||||
|
|
||||||
val service = retrofit.create(WeatherApiService::class.java)
|
val service = retrofit.create(WeatherApiService::class.java)
|
||||||
|
|
||||||
return withContext(Dispatchers.IO) {
|
|
||||||
val response = service.getWeather("$latitude", "$longitude", units, apiKey).execute()
|
val response = service.getWeather("$latitude", "$longitude", units, apiKey).execute()
|
||||||
if (response.isSuccessful) {
|
if (response.isSuccessful) {
|
||||||
val weatherResponse = response.body()
|
val weatherResponse = response.body()
|
||||||
if (weatherResponse != null) {
|
if (weatherResponse != null) {
|
||||||
// Cache the fetched weather data
|
// Cache the fetched weather data
|
||||||
context.cacheWeatherData(weatherResponse)
|
context.cacheWeatherData(weatherResponse)
|
||||||
weatherResponse
|
return WeatherResult.Success(weatherResponse)
|
||||||
} else {
|
} else {
|
||||||
throw NullPointerException("Weather response body is null")
|
return WeatherResult.Failure("Weather response body is null")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw Exception("Failed to fetch weather data: ${response.errorBody()}")
|
return WeatherResult.Failure("Failed to fetch weather data: ${response.errorBody()}")
|
||||||
}
|
}
|
||||||
|
} catch (e: UnknownHostException) {
|
||||||
|
return WeatherResult.Failure("Unknown Host : $baseURL")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return WeatherResult.Failure("${e.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import androidx.navigation.fragment.findNavController
|
|||||||
import com.github.droidworksstudio.common.capitalizeEachWord
|
import com.github.droidworksstudio.common.capitalizeEachWord
|
||||||
import com.github.droidworksstudio.common.hasInternetPermission
|
import com.github.droidworksstudio.common.hasInternetPermission
|
||||||
import com.github.droidworksstudio.common.hideKeyboard
|
import com.github.droidworksstudio.common.hideKeyboard
|
||||||
|
import com.github.droidworksstudio.common.showLongToast
|
||||||
import com.github.droidworksstudio.launcher.R
|
import com.github.droidworksstudio.launcher.R
|
||||||
import com.github.droidworksstudio.launcher.databinding.FragmentWidgetsBinding
|
import com.github.droidworksstudio.launcher.databinding.FragmentWidgetsBinding
|
||||||
import com.github.droidworksstudio.launcher.helper.AppHelper
|
import com.github.droidworksstudio.launcher.helper.AppHelper
|
||||||
@@ -36,7 +37,9 @@ import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
|
|||||||
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
|
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
|
||||||
import com.github.droidworksstudio.launcher.utils.Constants
|
import com.github.droidworksstudio.launcher.utils.Constants
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@@ -120,6 +123,7 @@ class WidgetFragment : Fragment(),
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
private fun setupWeatherWidget() {
|
private fun setupWeatherWidget() {
|
||||||
val sharedPreferences =
|
val sharedPreferences =
|
||||||
context.getSharedPreferences(Constants.WEATHER_PREFS, Context.MODE_PRIVATE)
|
context.getSharedPreferences(Constants.WEATHER_PREFS, Context.MODE_PRIVATE)
|
||||||
@@ -139,7 +143,9 @@ class WidgetFragment : Fragment(),
|
|||||||
if (!showWeatherWidget || !context.hasInternetPermission()) return@launch
|
if (!showWeatherWidget || !context.hasInternetPermission()) return@launch
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val weatherDeferred = async { appHelper.fetchWeatherData(context, latitude, longitude) }
|
val weatherDeferred = GlobalScope.async {
|
||||||
|
appHelper.fetchWeatherData(context, latitude, longitude)
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare UI elements concurrently
|
// Prepare UI elements concurrently
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
@@ -163,40 +169,50 @@ class WidgetFragment : Fragment(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val weatherResponse = weatherDeferred.await()
|
val result = weatherDeferred.await()
|
||||||
Log.d("weatherResponse", "$weatherResponse")
|
Log.d("weatherResponse", "$result")
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
when (result) {
|
||||||
val timestamp = convertTimestampToReadableDate(weatherResponse.dt)
|
is AppHelper.WeatherResult.Success -> {
|
||||||
binding.apply {
|
val weatherResponse = result.weatherResponse
|
||||||
weatherCity.text = getString(R.string.widget_weather_location, weatherResponse.name, weatherResponse.sys.country)
|
|
||||||
weatherTemperature.text = getString(R.string.widget_weather_temp, weatherResponse.main.temp, temperatureScale)
|
|
||||||
weatherDescription.text = getString(R.string.widget_weather_description, weatherResponse.weather[0].description).capitalizeEachWord()
|
|
||||||
weatherWind.text = getString(R.string.widget_weather_wind, weatherResponse.wind.speed, speedScale)
|
|
||||||
weatherHumidity.text = getString(R.string.widget_weather_humidity, weatherResponse.main.humidity)
|
|
||||||
weatherLastRun.text = timestamp
|
|
||||||
weatherRefresh.text = getString(R.string.widget_weather_refresh, getString(R.string.refresh_icon))
|
|
||||||
|
|
||||||
val weatherIconBitmap = createWeatherIcon(context, setWeatherIcon(context, weatherResponse.weather[0].id))
|
withContext(Dispatchers.Main) {
|
||||||
weatherIcon.setImageBitmap(weatherIconBitmap) // Ensure this matches your ImageView ID
|
val timestamp = convertTimestampToReadableDate(weatherResponse.dt)
|
||||||
weatherIcon.setColorFilter(widgetTextColor)
|
binding.apply {
|
||||||
|
weatherCity.text = getString(R.string.widget_weather_location, weatherResponse.name, weatherResponse.sys.country)
|
||||||
|
weatherTemperature.text = getString(R.string.widget_weather_temp, weatherResponse.main.temp, temperatureScale)
|
||||||
|
weatherDescription.text = getString(R.string.widget_weather_description, weatherResponse.weather[0].description).capitalizeEachWord()
|
||||||
|
weatherWind.text = getString(R.string.widget_weather_wind, weatherResponse.wind.speed, speedScale)
|
||||||
|
weatherHumidity.text = getString(R.string.widget_weather_humidity, weatherResponse.main.humidity)
|
||||||
|
weatherLastRun.text = timestamp
|
||||||
|
weatherRefresh.text = getString(R.string.widget_weather_refresh, getString(R.string.refresh_icon))
|
||||||
|
|
||||||
val sunriseIconBitmap = createSunIcon(context, getString(R.string.sunrise_icon))
|
val weatherIconBitmap = createWeatherIcon(context, setWeatherIcon(context, weatherResponse.weather[0].id))
|
||||||
sunriseIcon.setImageBitmap(sunriseIconBitmap)
|
weatherIcon.setImageBitmap(weatherIconBitmap) // Ensure this matches your ImageView ID
|
||||||
sunriseIcon.setColorFilter(widgetTextColor)
|
weatherIcon.setColorFilter(widgetTextColor)
|
||||||
|
|
||||||
val sunsetIconBitmap = createSunIcon(context, getString(R.string.sunset_icon))
|
val sunriseIconBitmap = createSunIcon(context, getString(R.string.sunrise_icon))
|
||||||
sunsetIcon.setImageBitmap(sunsetIconBitmap)
|
sunriseIcon.setImageBitmap(sunriseIconBitmap)
|
||||||
sunsetIcon.setColorFilter(widgetTextColor)
|
sunriseIcon.setColorFilter(widgetTextColor)
|
||||||
|
|
||||||
val sunriseTime = convertTimestampToReadableDate(weatherResponse.sys.sunrise)
|
val sunsetIconBitmap = createSunIcon(context, getString(R.string.sunset_icon))
|
||||||
sunriseText.text = getString(R.string.widget_sunrise_time, sunriseTime)
|
sunsetIcon.setImageBitmap(sunsetIconBitmap)
|
||||||
|
sunsetIcon.setColorFilter(widgetTextColor)
|
||||||
|
|
||||||
val sunsetTime = convertTimestampToReadableDate(weatherResponse.sys.sunset)
|
val sunriseTime = convertTimestampToReadableDate(weatherResponse.sys.sunrise)
|
||||||
sunsetText.text = getString(R.string.widget_sunset_time, sunsetTime)
|
sunriseText.text = getString(R.string.widget_sunrise_time, sunriseTime)
|
||||||
|
|
||||||
|
val sunsetTime = convertTimestampToReadableDate(weatherResponse.sys.sunset)
|
||||||
|
sunsetText.text = getString(R.string.widget_sunset_time, sunsetTime)
|
||||||
|
|
||||||
weatherRoot.visibility = View.VISIBLE
|
weatherRoot.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is AppHelper.WeatherResult.Failure -> {
|
||||||
|
val errorMessage = result.errorMessage
|
||||||
|
context.showLongToast(errorMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
|||||||
Reference in New Issue
Block a user