Update the providers

This commit is contained in:
Tommaso Berlose 2020-10-06 18:11:53 +02:00
parent bd4869540b
commit 1644fb7682
20 changed files with 587 additions and 146 deletions

View File

@ -22,6 +22,7 @@
android:name=".AWApplication" android:name=".AWApplication"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
tools:ignore="LockedOrientationActivity"> tools:ignore="LockedOrientationActivity">
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main" android:screenOrientation="portrait"> <activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main" android:screenOrientation="portrait">

View File

@ -42,15 +42,11 @@ object Constants {
enum class WeatherProvider(val value: Int) { enum class WeatherProvider(val value: Int) {
OPEN_WEATHER(0), OPEN_WEATHER(0),
WEATHER_BIT(1), WEATHER_BIT(1),
FORECA(2), WEATHER_API(2),
HERE(3), HERE(3),
ACCUWEATHER(4), ACCUWEATHER(4),
WEATHER_GOV(5), WEATHER_GOV(5),
YR(6), YR(6);
SMHI(7),
WEATHER_CA(8),
BOM(9),
METEOFRANCE(10);
companion object { companion object {
private val map = WeatherProvider.values().associateBy(WeatherProvider::value) private val map = WeatherProvider.values().associateBy(WeatherProvider::value)

View File

@ -38,7 +38,11 @@ object Preferences : KotprefModel() {
var calendarAppPackage by stringPref(key = "PREF_CALENDAR_APP_PACKAGE", default = "") var calendarAppPackage by stringPref(key = "PREF_CALENDAR_APP_PACKAGE", default = "")
var weatherAppName by stringPref(key = "PREF_WEATHER_APP_NAME", default = "") var weatherAppName by stringPref(key = "PREF_WEATHER_APP_NAME", default = "")
var weatherAppPackage by stringPref(key = "PREF_WEATHER_APP_PACKAGE", default = "") var weatherAppPackage by stringPref(key = "PREF_WEATHER_APP_PACKAGE", default = "")
var weatherProviderApi by stringPref(key = "PREF_WEATHER_PROVIDER_API_KEY", default = "") var weatherProviderApiOpen by stringPref(key = "PREF_WEATHER_PROVIDER_API_KEY", default = "")
var weatherProviderApiHere by stringPref(default = "")
var weatherProviderApiWeatherApi by stringPref(default = "")
var weatherProviderApiWeatherBit by stringPref(default = "")
var weatherProviderApiAccuweather by stringPref(default = "")
var weatherProvider by intPref(default = Constants.WeatherProvider.OPEN_WEATHER.value) var weatherProvider by intPref(default = Constants.WeatherProvider.OPEN_WEATHER.value)
var weatherProviderError by stringPref(default = "") var weatherProviderError by stringPref(default = "")
var weatherProviderLocationError by stringPref(default = "") var weatherProviderLocationError by stringPref(default = "")

View File

@ -52,15 +52,11 @@ object WeatherHelper {
return context.getString(when(provider) { return context.getString(when(provider) {
Constants.WeatherProvider.OPEN_WEATHER -> R.string.settings_weather_provider_open_weather Constants.WeatherProvider.OPEN_WEATHER -> R.string.settings_weather_provider_open_weather
Constants.WeatherProvider.WEATHER_BIT -> R.string.settings_weather_provider_weatherbit Constants.WeatherProvider.WEATHER_BIT -> R.string.settings_weather_provider_weatherbit
Constants.WeatherProvider.FORECA -> R.string.settings_weather_provider_foreca Constants.WeatherProvider.WEATHER_API -> R.string.settings_weather_provider_weather_api
Constants.WeatherProvider.HERE -> R.string.settings_weather_provider_here Constants.WeatherProvider.HERE -> R.string.settings_weather_provider_here
Constants.WeatherProvider.ACCUWEATHER -> R.string.settings_weather_provider_accuweather Constants.WeatherProvider.ACCUWEATHER -> R.string.settings_weather_provider_accuweather
Constants.WeatherProvider.WEATHER_GOV -> R.string.settings_weather_provider_weather_gov Constants.WeatherProvider.WEATHER_GOV -> R.string.settings_weather_provider_weather_gov
Constants.WeatherProvider.YR -> R.string.settings_weather_provider_yr Constants.WeatherProvider.YR -> R.string.settings_weather_provider_yr
Constants.WeatherProvider.SMHI -> R.string.settings_weather_provider_smhi
Constants.WeatherProvider.WEATHER_CA -> R.string.settings_weather_provider_weather_ca
Constants.WeatherProvider.BOM -> R.string.settings_weather_provider_bom
Constants.WeatherProvider.METEOFRANCE -> R.string.settings_weather_provider_meteofrance
}) })
} }
@ -68,15 +64,11 @@ object WeatherHelper {
return context.getString(when(Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) { return context.getString(when(Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
Constants.WeatherProvider.OPEN_WEATHER -> R.string.action_open_provider_open_weather Constants.WeatherProvider.OPEN_WEATHER -> R.string.action_open_provider_open_weather
Constants.WeatherProvider.WEATHER_BIT -> R.string.action_open_provider_weatherbit Constants.WeatherProvider.WEATHER_BIT -> R.string.action_open_provider_weatherbit
Constants.WeatherProvider.FORECA -> R.string.action_open_provider_foreca Constants.WeatherProvider.WEATHER_API -> R.string.action_open_provider_weatherapi
Constants.WeatherProvider.HERE -> R.string.action_open_provider_here Constants.WeatherProvider.HERE -> R.string.action_open_provider_here
Constants.WeatherProvider.ACCUWEATHER -> R.string.action_open_provider_accuweather Constants.WeatherProvider.ACCUWEATHER -> R.string.action_open_provider_accuweather
Constants.WeatherProvider.WEATHER_GOV -> R.string.action_open_provider_weather_gov Constants.WeatherProvider.WEATHER_GOV -> R.string.action_open_provider_weather_gov
Constants.WeatherProvider.YR -> R.string.action_open_provider_yr Constants.WeatherProvider.YR -> R.string.action_open_provider_yr
Constants.WeatherProvider.SMHI -> R.string.action_open_provider_smhi
Constants.WeatherProvider.WEATHER_CA -> R.string.action_open_provider_weather_ca
Constants.WeatherProvider.BOM -> R.string.action_open_provider_bom
Constants.WeatherProvider.METEOFRANCE -> R.string.action_open_provider_meteofrance
else -> R.string.nothing else -> R.string.nothing
}) })
} }
@ -85,15 +77,11 @@ object WeatherHelper {
return context.getString(when(Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) { return context.getString(when(Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
Constants.WeatherProvider.OPEN_WEATHER -> R.string.weather_provider_info_open_weather_title Constants.WeatherProvider.OPEN_WEATHER -> R.string.weather_provider_info_open_weather_title
Constants.WeatherProvider.WEATHER_BIT -> R.string.weather_provider_info_weatherbit_title Constants.WeatherProvider.WEATHER_BIT -> R.string.weather_provider_info_weatherbit_title
Constants.WeatherProvider.FORECA -> R.string.weather_provider_info_foreca_title Constants.WeatherProvider.WEATHER_API -> R.string.weather_provider_info_weatherapi_title
Constants.WeatherProvider.HERE -> R.string.weather_provider_info_here_title Constants.WeatherProvider.HERE -> R.string.weather_provider_info_here_title
Constants.WeatherProvider.ACCUWEATHER -> R.string.weather_provider_info_accuweather_title Constants.WeatherProvider.ACCUWEATHER -> R.string.weather_provider_info_accuweather_title
Constants.WeatherProvider.WEATHER_GOV -> R.string.weather_provider_info_weather_gov_title Constants.WeatherProvider.WEATHER_GOV -> R.string.weather_provider_info_weather_gov_title
Constants.WeatherProvider.YR -> R.string.weather_provider_info_yr_title Constants.WeatherProvider.YR -> R.string.weather_provider_info_yr_title
Constants.WeatherProvider.SMHI -> R.string.weather_provider_info_smhi_title
Constants.WeatherProvider.WEATHER_CA -> R.string.weather_provider_info_weather_ca_title
Constants.WeatherProvider.BOM -> R.string.weather_provider_info_bom_title
Constants.WeatherProvider.METEOFRANCE -> R.string.weather_provider_info_meteofrance_title
else -> R.string.nothing else -> R.string.nothing
}) })
} }
@ -102,15 +90,11 @@ object WeatherHelper {
return context.getString(when(Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) { return context.getString(when(Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
Constants.WeatherProvider.OPEN_WEATHER -> R.string.weather_provider_info_open_weather_subtitle Constants.WeatherProvider.OPEN_WEATHER -> R.string.weather_provider_info_open_weather_subtitle
Constants.WeatherProvider.WEATHER_BIT -> R.string.weather_provider_info_weatherbit_subtitle Constants.WeatherProvider.WEATHER_BIT -> R.string.weather_provider_info_weatherbit_subtitle
Constants.WeatherProvider.FORECA -> R.string.weather_provider_info_foreca_subtitle Constants.WeatherProvider.WEATHER_API -> R.string.weather_provider_info_weatherapi_subtitle
Constants.WeatherProvider.HERE -> R.string.weather_provider_info_here_subtitle Constants.WeatherProvider.HERE -> R.string.weather_provider_info_here_subtitle
Constants.WeatherProvider.ACCUWEATHER -> R.string.weather_provider_info_accuweather_subtitle Constants.WeatherProvider.ACCUWEATHER -> R.string.weather_provider_info_accuweather_subtitle
Constants.WeatherProvider.WEATHER_GOV -> R.string.weather_provider_info_weather_gov_subtitle Constants.WeatherProvider.WEATHER_GOV -> R.string.weather_provider_info_weather_gov_subtitle
Constants.WeatherProvider.YR -> R.string.weather_provider_info_yr_subtitle Constants.WeatherProvider.YR -> R.string.weather_provider_info_yr_subtitle
Constants.WeatherProvider.SMHI -> R.string.weather_provider_info_smhi_subtitle
Constants.WeatherProvider.WEATHER_CA -> R.string.weather_provider_info_weather_ca_subtitle
Constants.WeatherProvider.BOM -> R.string.weather_provider_info_bom_subtitle
Constants.WeatherProvider.METEOFRANCE -> R.string.weather_provider_info_meteofrance_subtitle
else -> R.string.nothing else -> R.string.nothing
}) })
} }
@ -118,16 +102,12 @@ object WeatherHelper {
fun getProviderLink(): String { fun getProviderLink(): String {
return when(Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) { return when(Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
Constants.WeatherProvider.OPEN_WEATHER -> "https://home.openweathermap.org/users/sign_up" Constants.WeatherProvider.OPEN_WEATHER -> "https://home.openweathermap.org/users/sign_up"
Constants.WeatherProvider.WEATHER_BIT -> "" Constants.WeatherProvider.WEATHER_BIT -> "https://www.weatherbit.io/account/create"
Constants.WeatherProvider.FORECA -> "" Constants.WeatherProvider.WEATHER_API -> "https://www.weatherapi.com/signup.aspx"
Constants.WeatherProvider.HERE -> "" Constants.WeatherProvider.HERE -> "https://developer.here.com/sign-up?create=Freemium-Basic&keepState=true&step=account"
Constants.WeatherProvider.ACCUWEATHER -> "" Constants.WeatherProvider.ACCUWEATHER -> "https://developer.accuweather.com/user/register"
Constants.WeatherProvider.WEATHER_GOV -> "" Constants.WeatherProvider.WEATHER_GOV -> "http://www.weather.gov/"
Constants.WeatherProvider.YR -> "" Constants.WeatherProvider.YR -> "https://www.yr.no/"
Constants.WeatherProvider.SMHI -> ""
Constants.WeatherProvider.WEATHER_CA -> ""
Constants.WeatherProvider.BOM -> ""
Constants.WeatherProvider.METEOFRANCE -> ""
else -> "" else -> ""
} }
} }
@ -135,16 +115,12 @@ object WeatherHelper {
fun isKeyRequired(): Boolean = when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) { fun isKeyRequired(): Boolean = when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
Constants.WeatherProvider.OPEN_WEATHER, Constants.WeatherProvider.OPEN_WEATHER,
Constants.WeatherProvider.WEATHER_BIT, Constants.WeatherProvider.WEATHER_BIT,
Constants.WeatherProvider.FORECA, Constants.WeatherProvider.WEATHER_API,
Constants.WeatherProvider.HERE, Constants.WeatherProvider.HERE,
Constants.WeatherProvider.ACCUWEATHER, Constants.WeatherProvider.ACCUWEATHER -> true
Constants.WeatherProvider.YR,
Constants.WeatherProvider.SMHI,
Constants.WeatherProvider.WEATHER_CA,
Constants.WeatherProvider.BOM,
Constants.WeatherProvider.METEOFRANCE -> true
Constants.WeatherProvider.WEATHER_GOV -> false Constants.WeatherProvider.WEATHER_GOV,
Constants.WeatherProvider.YR -> false
else -> true else -> true
} }
@ -389,4 +365,90 @@ object WeatherHelper {
else -> "" else -> ""
} + if (isDaytime) "d" else "n" } + if (isDaytime) "d" else "n"
fun getWeatherBitIcon(iconString: String): String = when {
iconString.contains("t01") -> "11"
iconString.contains("t02") -> "09"
iconString.contains("t03") -> "09"
iconString.contains("t04") -> "09"
iconString.contains("t05") -> "09"
iconString.contains("d01") -> "10"
iconString.contains("d02") -> "10"
iconString.contains("d03") -> "10"
iconString.contains("r01") -> "10"
iconString.contains("r02") -> "10"
iconString.contains("r03") -> "10"
iconString.contains("f01") -> "10"
iconString.contains("r04") -> "10"
iconString.contains("r05") -> "10"
iconString.contains("r06") -> "10"
iconString.contains("s01") -> "13"
iconString.contains("s02") -> "13"
iconString.contains("s03") -> "13"
iconString.contains("s04") -> "81"
iconString.contains("s05") -> "90"
iconString.contains("s06") -> "13"
iconString.contains("a01") -> "82"
iconString.contains("a02") -> "82"
iconString.contains("a03") -> "82"
iconString.contains("a04") -> "82"
iconString.contains("a05") -> "82"
iconString.contains("a06") -> "82"
iconString.contains("c01") -> "01"
iconString.contains("c02") -> "02"
iconString.contains("c03") -> "04"
iconString.contains("c04") -> "04"
else -> ""
} + if (iconString.contains("d")) "d" else "n"
fun getWeatherApiIcon(icon: Int, isDaytime: Boolean): String = when(icon) {
1000 -> "01"
1003 -> "02"
1006 -> "03"
1009 -> "04"
1030 -> "82"
1063 -> "10"
1066 -> "10"
1069 -> "10"
1072 -> "81"
1087 -> "11"
1114 -> "13"
1117 -> "09"
1135 -> "82"
1147 -> "82"
1150 -> "10"
1153 -> "10"
1168 -> "10"
1171 -> "10"
1180 -> "10"
1183 -> "10"
1186 -> "10"
1189 -> "10"
1192 -> "10"
1195 -> "10"
1198 -> "81"
1201 -> "81"
1204 -> "13"
1207 -> "13"
1210 -> "13"
1213 -> "13"
1216 -> "13"
1219 -> "13"
1222 -> "13"
1225 -> "13"
1237 -> "13"
1240 -> "10"
1243 -> "10"
1246 -> "10"
1249 -> "13"
1252 -> "13"
1255 -> "13"
1258 -> "13"
1261 -> "13"
1264 -> "13"
1273 -> "09"
1276 -> "09"
1279 -> "13"
1282 -> "13"
else -> ""
} + if (isDaytime) "d" else "n"
} }

View File

@ -13,12 +13,11 @@ import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
import com.tommasoberlose.anotherwidget.network.repository.WeatherGovRepository import com.tommasoberlose.anotherwidget.network.repository.*
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import java.lang.Exception import java.lang.Exception
@ -32,6 +31,11 @@ class WeatherNetworkApi(val context: Context) {
when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) { when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
Constants.WeatherProvider.OPEN_WEATHER -> useOpenWeatherMap(context) Constants.WeatherProvider.OPEN_WEATHER -> useOpenWeatherMap(context)
Constants.WeatherProvider.WEATHER_GOV -> useWeatherGov(context) Constants.WeatherProvider.WEATHER_GOV -> useWeatherGov(context)
Constants.WeatherProvider.WEATHER_BIT -> useWeatherBitProvider(context)
Constants.WeatherProvider.WEATHER_API -> useWeatherApiProvider(context)
Constants.WeatherProvider.HERE -> useHereProvider(context)
Constants.WeatherProvider.ACCUWEATHER -> useAccuweatherProvider(context)
Constants.WeatherProvider.YR -> useYrProvider(context)
} }
} else { } else {
WeatherHelper.removeWeather( WeatherHelper.removeWeather(
@ -41,8 +45,8 @@ class WeatherNetworkApi(val context: Context) {
} }
private fun useOpenWeatherMap(context: Context) { private fun useOpenWeatherMap(context: Context) {
if (Preferences.weatherProviderApi != "" ) { if (Preferences.weatherProviderApiOpen != "" ) {
val helper = OpenWeatherMapHelper(Preferences.weatherProviderApi) val helper = OpenWeatherMapHelper(Preferences.weatherProviderApiOpen)
helper.setUnits(if (Preferences.weatherTempUnit == "F") Units.IMPERIAL else Units.METRIC) helper.setUnits(if (Preferences.weatherTempUnit == "F") Units.IMPERIAL else Units.METRIC)
helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object : helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object :
CurrentWeatherCallback { CurrentWeatherCallback {
@ -118,13 +122,115 @@ class WeatherNetworkApi(val context: Context) {
} }
} }
} catch(ex: Exception) { } catch(ex: Exception) {
} }
} }
is NetworkResponse.ServerError -> { is NetworkResponse.ServerError -> {
if (pointsResponse.body?.containsKey("status") == true && (pointsResponse.body?.get("status") as Double).toInt() == 404) { if (pointsResponse.body?.containsKey("status") == true && (pointsResponse.body?.get("status") as Double).toInt() == 404) {
Preferences.weatherProviderError = "" Preferences.weatherProviderError = ""
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_wrong_location) Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_wrong_location)
}
WeatherHelper.removeWeather(
context
)
}
}
}
}
private fun useHereProvider(context: Context) {
CoroutineScope(Dispatchers.IO).launch {
val repository = HereRepository()
when (val response = repository.getWeather()) {
is NetworkResponse.Success -> {
try {
Log.d("ciao - here", response.body.toString())
} catch(ex: Exception) {
}
}
is NetworkResponse.ServerError -> {
WeatherHelper.removeWeather(
context
)
}
}
}
}
private fun useWeatherBitProvider(context: Context) {
CoroutineScope(Dispatchers.IO).launch {
val repository = WeatherbitRepository()
when (val response = repository.getWeather()) {
is NetworkResponse.Success -> {
try {
val data = response.body["data"] as List<LinkedTreeMap<String, Any>>?
data?.first()?.let {
val temp = it["temp"] as Double
val weatherInfo = it["weather"] as LinkedTreeMap<String, Any>
val iconCode = weatherInfo["icon"] as String
Preferences.weatherTemp = temp.toFloat()
Preferences.weatherIcon = WeatherHelper.getWeatherBitIcon(iconCode)
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
MainWidget.updateWidget(context)
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
}
} catch(ex: Exception) {
}
}
is NetworkResponse.ServerError -> {
when (response.code) {
403 -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_invalid_key)
}
}
WeatherHelper.removeWeather(
context
)
}
}
}
}
private fun useWeatherApiProvider(context: Context) {
CoroutineScope(Dispatchers.IO).launch {
val repository = WeatherApiRepository()
when (val response = repository.getWeather()) {
is NetworkResponse.Success -> {
try {
val current = response.body["current"] as LinkedTreeMap<String, Any>?
current?.let {
val tempC = current["temp_c"] as Double
val tempF = current["temp_f"] as Double
val isDay = current["is_day"] as Double
val condition = current["condition"] as LinkedTreeMap<String, Any>
val iconCode = condition["code"] as Double
Preferences.weatherTemp = if (Preferences.weatherTempUnit == "F") tempF.toFloat() else tempC.toFloat()
Preferences.weatherIcon = WeatherHelper.getWeatherApiIcon(iconCode.toInt(), isDay.toInt() == 1)
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
MainWidget.updateWidget(context)
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
}
} catch(ex: Exception) {
Log.d("ciao", ex.localizedMessage)
}
}
is NetworkResponse.ServerError -> {
when (response.code) {
401 -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_invalid_key)
}
403 -> {
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_expired_key)
}
}
WeatherHelper.removeWeather( WeatherHelper.removeWeather(
context context
@ -132,7 +238,47 @@ class WeatherNetworkApi(val context: Context) {
} }
} }
} }
}
private fun useAccuweatherProvider(context: Context) {
CoroutineScope(Dispatchers.IO).launch {
val repository = AccuweatherRepository()
// when (val response = repository.getWeather()) {
// is NetworkResponse.Success -> {
// try {
// Log.d("ciao", response.body.toString())
// } catch(ex: Exception) {
//
// }
// }
// is NetworkResponse.ServerError -> {
// WeatherHelper.removeWeather(
// context
// )
// }
// }
}
}
private fun useYrProvider(context: Context) {
CoroutineScope(Dispatchers.IO).launch {
val repository = YrRepository()
when (val response = repository.getWeather()) {
is NetworkResponse.Success -> {
try {
Log.d("ciao - yr", response.body.toString())
} catch(ex: Exception) {
} }
} }
is NetworkResponse.ServerError -> {
WeatherHelper.removeWeather(
context
)
}
}
}
}
} }

View File

@ -0,0 +1,74 @@
package com.tommasoberlose.anotherwidget.network.api
import com.haroldadmin.cnradapter.NetworkResponse
import retrofit2.http.*
object ApiServices {
interface WeatherGovApiService {
@Headers("User-Agent: (Another Widget, tommaso.berlose@gmail.com)")
@GET("points/{latitude},{longitude}")
suspend fun getGridPoints(
@Path("latitude") latitude: String,
@Path("longitude") longitude: String
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
@Headers("User-Agent: (Another Widget, tommaso.berlose@gmail.com)")
@GET("gridpoints/{gridId}/{gridX},{gridY}/forecast")
suspend fun getWeather(
@Path("gridId") gridId: String,
@Path("gridX") gridX: Int,
@Path("gridY") gridY: Int,
@Query("units") unit: String
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
}
interface WeatherBitService {
@GET("current")
suspend fun getWeather(
@Query("key") key: String,
@Query("lat") lat: String,
@Query("lon") lon: String,
@Query("units") units: String,
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
}
interface WeatherApiService {
@Headers("Accept: application/json")
@GET("current.json")
suspend fun getWeather(
@Query("key") key: String,
@Query("q") location: String,
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
}
interface HereService {
@GET("report.json")
suspend fun getWeather(
@Query("apiKey") apiKey: String,
@Query("latitude") latitude: String,
@Query("longitude") longitude: String,
@Query("product") product: String,
@Query("oneobservation") oneobservation: Boolean,
@Query("metric") metric: Boolean,
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
}
interface AccuweatherService {
@GET("")
suspend fun getWeather(
@Path("gridId") gridId: String,
@Path("gridX") gridX: Int,
@Path("gridY") gridY: Int,
@Query("units") unit: String
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
}
interface YrService {
@Headers("User-Agent: AnotherWidget")
@GET("compact.json")
suspend fun getWeather(
@Query("lat") lat: String,
@Query("lon") lon: String,
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
}
}

View File

@ -1,13 +0,0 @@
package com.tommasoberlose.anotherwidget.network.api
import com.haroldadmin.cnradapter.NetworkResponse
import retrofit2.http.*
interface WeatherGovApiService {
@GET("points/{latitude},{longitude}")
suspend fun getGridPoints(@Path("latitude") latitude: String, @Path("longitude") longitude: String): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
@Headers("User-Agent: (Another Widget, tommaso.berlose@gmail.com)")
@GET("gridpoints/{gridId}/{gridX},{gridY}/forecast")
suspend fun getWeather(@Path("gridId") gridId: String, @Path("gridX") gridX: Int, @Path("gridY") gridY: Int, @Query("units") unit: String): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
}

View File

@ -0,0 +1,25 @@
package com.tommasoberlose.anotherwidget.network.repository
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
import com.tommasoberlose.anotherwidget.network.api.ApiServices
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class AccuweatherRepository {
/* ACCUWEATHER */
private val apiServiceAccu: ApiServices.AccuweatherService = getRetrofit().create(ApiServices.AccuweatherService::class.java)
suspend fun getWeather(): Nothing = TODO()
companion object {
private const val BASE_URL_ACCU = ""
private fun getRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL_ACCU)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(NetworkResponseAdapterFactory())
.build()
}
}
}

View File

@ -0,0 +1,26 @@
package com.tommasoberlose.anotherwidget.network.repository
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.network.api.ApiServices
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class HereRepository {
/* HERE */
private val apiServiceHere: ApiServices.HereService = getRetrofit().create(ApiServices.HereService::class.java)
suspend fun getWeather() = apiServiceHere.getWeather(Preferences.weatherProviderApiHere, Preferences.customLocationLat, Preferences.customLocationLon, "observation", true, Preferences.weatherTempUnit != "F")
companion object {
private const val BASE_URL_HERE = "https://weather.ls.hereapi.com/weather/1.0/"
private fun getRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL_HERE)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(NetworkResponseAdapterFactory())
.build()
}
}
}

View File

@ -0,0 +1,26 @@
package com.tommasoberlose.anotherwidget.network.repository
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.network.api.ApiServices
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class WeatherApiRepository {
/* WEATHER API*/
private val apiServiceApi: ApiServices.WeatherApiService = getRetrofit().create(ApiServices.WeatherApiService::class.java)
suspend fun getWeather() = apiServiceApi.getWeather(Preferences.weatherProviderApiWeatherApi, "${Preferences.customLocationLat},${Preferences.customLocationLon}")
companion object {
private const val BASE_URL_API = "http://api.weatherapi.com/v1/"
private fun getRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL_API)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(NetworkResponseAdapterFactory())
.build()
}
}
}

View File

@ -1,22 +1,23 @@
package com.tommasoberlose.anotherwidget.network.repository package com.tommasoberlose.anotherwidget.network.repository
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
import com.tommasoberlose.anotherwidget.network.api.WeatherGovApiService import com.tommasoberlose.anotherwidget.network.api.ApiServices
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory import retrofit2.converter.gson.GsonConverterFactory
class WeatherGovRepository { class WeatherGovRepository {
private val apiService: WeatherGovApiService = getRetrofit().create(WeatherGovApiService::class.java) /* WEATHER GOV*/
private val apiServiceGov: ApiServices.WeatherGovApiService = getRetrofit().create(ApiServices.WeatherGovApiService::class.java)
suspend fun getGridPoints(latitude: String, longitude: String) = apiService.getGridPoints(latitude, longitude) suspend fun getGridPoints(latitude: String, longitude: String) = apiServiceGov.getGridPoints(latitude, longitude)
suspend fun getWeather(gridId: String, gridX: Double, gridY: Double, unit: String) = apiService.getWeather(gridId, gridX.toInt(), gridY.toInt(), unit) suspend fun getWeather(gridId: String, gridX: Double, gridY: Double, unit: String) = apiServiceGov.getWeather(gridId, gridX.toInt(), gridY.toInt(), unit)
companion object { companion object {
private const val BASE_URL = "https://api.weather.gov/" private const val BASE_URL_GOV = "https://api.weather.gov/"
private fun getRetrofit(): Retrofit { private fun getRetrofit(): Retrofit {
return Retrofit.Builder() return Retrofit.Builder()
.baseUrl(BASE_URL) .baseUrl(BASE_URL_GOV)
.addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(NetworkResponseAdapterFactory()) .addCallAdapterFactory(NetworkResponseAdapterFactory())
.build() .build()

View File

@ -0,0 +1,26 @@
package com.tommasoberlose.anotherwidget.network.repository
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.network.api.ApiServices
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class WeatherbitRepository {
/* BIT */
private val apiServiceBit: ApiServices.WeatherBitService = getRetrofit().create(ApiServices.WeatherBitService::class.java)
suspend fun getWeather() = apiServiceBit.getWeather(Preferences.weatherProviderApiWeatherBit, Preferences.customLocationLat, Preferences.customLocationLon, if (Preferences.weatherTempUnit == "F") "I" else "M")
companion object {
private const val BASE_URL_BIT = "https://api.weatherbit.io/v2.0/"
private fun getRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL_BIT)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(NetworkResponseAdapterFactory())
.build()
}
}
}

View File

@ -0,0 +1,26 @@
package com.tommasoberlose.anotherwidget.network.repository
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.network.api.ApiServices
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class YrRepository {
/* YR */
private val apiServiceYr: ApiServices.YrService = getRetrofit().create(ApiServices.YrService::class.java)
suspend fun getWeather() = apiServiceYr.getWeather(Preferences.customLocationLat, Preferences.customLocationLon)
companion object {
private const val BASE_URL_YR = "https://api.met.no/weatherapi/locationforecast/2.0/"
private fun getRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL_YR)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(NetworkResponseAdapterFactory())
.build()
}
}
}

View File

@ -5,7 +5,6 @@ import android.app.PendingIntent
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.util.Log
import com.tommasoberlose.anotherwidget.global.Actions import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
@ -33,7 +32,7 @@ class WeatherReceiver : BroadcastReceiver() {
fun setUpdates(context: Context) { fun setUpdates(context: Context) {
removeUpdates(context) removeUpdates(context)
if (Preferences.showWeather && Preferences.weatherProviderApi != "") { if (Preferences.showWeather) {
val interval = MINUTE * when (Preferences.weatherRefreshPeriod) { val interval = MINUTE * when (Preferences.weatherRefreshPeriod) {
0 -> 30 0 -> 30
1 -> 60 1 -> 60
@ -55,7 +54,7 @@ class WeatherReceiver : BroadcastReceiver() {
} }
fun setOneTimeUpdate(context: Context) { fun setOneTimeUpdate(context: Context) {
if (Preferences.showWeather && Preferences.weatherProviderApi != "") { if (Preferences.showWeather) {
listOf(10, 20, 30).forEach { listOf(10, 20, 30).forEach {
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
setExactAndAllowWhileIdle( setExactAndAllowWhileIdle(

View File

@ -1,33 +1,43 @@
package com.tommasoberlose.anotherwidget.ui.activities package com.tommasoberlose.anotherwidget.ui.activities
import android.animation.ValueAnimator
import android.app.Activity import android.app.Activity
import android.app.AlertDialog import android.content.Intent
import android.os.Build import android.content.pm.ResolveInfo
import android.os.Bundle import android.os.Bundle
import android.text.Html
import android.view.View import android.view.View
import android.widget.RelativeLayout import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.animation.addListener import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding
import com.tommasoberlose.anotherwidget.databinding.ActivityWeatherProviderBinding
import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
import com.tommasoberlose.anotherwidget.ui.viewmodels.ChooseApplicationViewModel
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.utils.collapse
import com.tommasoberlose.anotherwidget.utils.expand
import com.tommasoberlose.anotherwidget.utils.openURI import com.tommasoberlose.anotherwidget.utils.openURI
import kotlinx.android.synthetic.main.activity_choose_application.*
import kotlinx.android.synthetic.main.activity_weather_provider.* import kotlinx.android.synthetic.main.activity_weather_provider.*
import kotlinx.android.synthetic.main.the_widget_sans.* import kotlinx.android.synthetic.main.activity_weather_provider.action_back
import kotlinx.android.synthetic.main.activity_weather_provider.list_view
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import net.idik.lib.slimadapter.SlimAdapter
class WeatherProviderActivity : AppCompatActivity() { class WeatherProviderActivity : AppCompatActivity() {
private lateinit var adapter: SlimAdapter
private lateinit var viewModel: MainViewModel private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -35,39 +45,62 @@ class WeatherProviderActivity : AppCompatActivity() {
setContentView(R.layout.activity_weather_provider) setContentView(R.layout.activity_weather_provider)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java) viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
api_key.editText?.setText(Preferences.weatherProviderApi) api_key.editText?.setText(Preferences.weatherProviderApiOpen)
list_view.setHasFixedSize(true)
val mLayoutManager = LinearLayoutManager(this)
list_view.layoutManager = mLayoutManager
adapter = SlimAdapter.create()
adapter
.register<Int>(R.layout.list_item) { item, injector ->
val provider = Constants.WeatherProvider.fromInt(item)!!
injector
.text(R.id.text, WeatherHelper.getProviderName(this, provider))
.clicked(R.id.text) {
Preferences.weatherProvider = item
} }
}
.attachTo(list_view)
override fun onResume() { setupListener()
super.onResume()
setListener()
subscribeUi(viewModel) subscribeUi(viewModel)
} }
private fun subscribeUi(viewModel: MainViewModel) { private fun subscribeUi(viewModel: MainViewModel) {
viewModel.weatherProvider.observe(this, Observer { adapter.updateData(Constants.WeatherProvider.values().map { it.value })
weather_provider.editText?.setText(WeatherHelper.getProviderName(this, Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!).split("\n").first())
api_key_container.isVisible = WeatherHelper.isKeyRequired() // viewModel.weatherProvider.observe(this, Observer {
// weather_provider.editText?.setText(WeatherHelper.getProviderName(this, Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!).split("\n").first())
WeatherHelper.getProviderInfoTitle(this).let { //
info_title.text = it // api_key_container.isVisible = WeatherHelper.isKeyRequired()
info_title.isVisible = it != "" //
// WeatherHelper.getProviderInfoTitle(this).let {
// info_title.text = it
// info_title.isVisible = it != ""
// }
//
// WeatherHelper.getProviderInfoSubtitle(this).let {
// info_subtitle.text = it
// info_subtitle.isVisible = it != ""
// }
//
// action_open_provider.text = WeatherHelper.getProviderLinkName(this)
//
// api_key.editText?.setText(when (Constants.WeatherProvider.fromInt(it)) {
// Constants.WeatherProvider.OPEN_WEATHER -> Preferences.weatherProviderApiOpen
// Constants.WeatherProvider.WEATHER_BIT -> Preferences.weatherProviderApiWeatherBit
// Constants.WeatherProvider.WEATHER_API -> Preferences.weatherProviderApiWeatherApi
// Constants.WeatherProvider.HERE -> Preferences.weatherProviderApiHere
// Constants.WeatherProvider.ACCUWEATHER -> Preferences.weatherProviderApiAccuweather
// Constants.WeatherProvider.WEATHER_GOV,
// Constants.WeatherProvider.YR,
// null -> ""
// })
// })
} }
WeatherHelper.getProviderInfoSubtitle(this).let { private fun setupListener() {
info_subtitle.text = it
info_subtitle.isVisible = it != ""
}
action_open_provider.text = WeatherHelper.getProviderLinkName(this)
})
viewModel.weatherProviderApi
}
private fun setListener() {
action_back.setOnClickListener { action_back.setOnClickListener {
onBackPressed() onBackPressed()
} }
@ -79,7 +112,7 @@ class WeatherProviderActivity : AppCompatActivity() {
weather_provider_inner.setOnClickListener { weather_provider_inner.setOnClickListener {
if (Preferences.showWeather) { if (Preferences.showWeather) {
val dialog = BottomSheetMenu<Int>(this, header = getString(R.string.settings_weather_provider_api)).setSelectedValue(Preferences.weatherProvider) val dialog = BottomSheetMenu<Int>(this, header = getString(R.string.settings_weather_provider_api)).setSelectedValue(Preferences.weatherProvider)
(0 until 11).forEach { (0 until 7).forEach {
val item = Constants.WeatherProvider.fromInt(it) val item = Constants.WeatherProvider.fromInt(it)
dialog.addItem(WeatherHelper.getProviderName(this, item!!), it) dialog.addItem(WeatherHelper.getProviderName(this, item!!), it)
} }
@ -92,7 +125,14 @@ class WeatherProviderActivity : AppCompatActivity() {
api_key.editText?.addTextChangedListener { api_key.editText?.addTextChangedListener {
val key = it?.toString() ?: "" val key = it?.toString() ?: ""
Preferences.weatherProviderApi = key when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
Constants.WeatherProvider.OPEN_WEATHER -> Preferences.weatherProviderApiOpen = key
Constants.WeatherProvider.WEATHER_BIT -> Preferences.weatherProviderApiWeatherBit = key
Constants.WeatherProvider.WEATHER_API -> Preferences.weatherProviderApiWeatherApi = key
Constants.WeatherProvider.HERE -> Preferences.weatherProviderApiHere = key
Constants.WeatherProvider.ACCUWEATHER -> Preferences.weatherProviderApiAccuweather = key
else -> {}
}
} }
} }

View File

@ -2,8 +2,6 @@ package com.tommasoberlose.anotherwidget.ui.fragments
import android.Manifest import android.Manifest
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProviderInfo
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
@ -11,7 +9,6 @@ import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.Settings import android.provider.Settings
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.util.Log
import android.util.TypedValue import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -355,7 +352,7 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText) backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
badgeGravity = BadgeDrawable.TOP_END badgeGravity = BadgeDrawable.TOP_END
}?.isVisible = if (Preferences.showWeather) { }?.isVisible = if (Preferences.showWeather) {
(WeatherHelper.isKeyRequired() && Preferences.weatherProviderApi == "") (WeatherHelper.isKeyRequired() && Preferences.weatherProviderApiOpen == "")
|| (Preferences.customLocationAdd == "" && activity?.checkGrantedPermission( || (Preferences.customLocationAdd == "" && activity?.checkGrantedPermission(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
) != true) ) != true)

View File

@ -170,9 +170,11 @@ class WeatherTabFragment : Fragment() {
if (activity?.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION) == true) { if (activity?.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION) == true) {
location_permission_alert?.isVisible = false location_permission_alert?.isVisible = false
background_location_warning.isVisible = Preferences.customLocationAdd == ""
WeatherReceiver.setUpdates(requireContext()) WeatherReceiver.setUpdates(requireContext())
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") { } else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
location_permission_alert?.isVisible = true location_permission_alert?.isVisible = true
background_location_warning.isVisible = false
location_permission_alert?.setOnClickListener { location_permission_alert?.setOnClickListener {
MaterialBottomSheetDialog(requireContext(), message = getString(R.string.background_location_warning)) MaterialBottomSheetDialog(requireContext(), message = getString(R.string.background_location_warning))
.setPositiveButton(getString(android.R.string.ok)) { .setPositiveButton(getString(android.R.string.ok)) {
@ -283,7 +285,7 @@ class WeatherTabFragment : Fragment() {
MainWidget.updateWidget(requireContext()) MainWidget.updateWidget(requireContext())
} }
RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> { RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
WeatherReceiver.setOneTimeUpdate(requireContext()) checkLocationPermission()
} }
} }
} }

View File

@ -64,7 +64,7 @@ class MainViewModel : ViewModel() {
val weatherRefreshPeriod = Preferences.asLiveData(Preferences::weatherRefreshPeriod) val weatherRefreshPeriod = Preferences.asLiveData(Preferences::weatherRefreshPeriod)
val weatherAppName = Preferences.asLiveData(Preferences::weatherAppName) val weatherAppName = Preferences.asLiveData(Preferences::weatherAppName)
val weatherProviderApi = Preferences.asLiveData(Preferences::weatherProviderApi) val weatherProviderApi = Preferences.asLiveData(Preferences::weatherProviderApiOpen)
val customLocationAdd = Preferences.asLiveData(Preferences::customLocationAdd) val customLocationAdd = Preferences.asLiveData(Preferences::customLocationAdd)

View File

@ -50,8 +50,26 @@
android:textAppearance="@style/TextAppearance.MaterialComponents.Button"/> android:textAppearance="@style/TextAppearance.MaterialComponents.Button"/>
</RelativeLayout> </RelativeLayout>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.core.widget.ContentLoadingProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
android:indeterminateTint="@color/colorAccent"
android:layout_marginTop="-7dp"
android:id="@+id/loader"
style="@style/Widget.AppCompat.ProgressBar.Horizontal" />
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/list_view" />
</RelativeLayout>
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
android:visibility="gone"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -132,56 +132,41 @@
<string name="settings_weather_provider_open_weather">Open Weather Map</string> <string name="settings_weather_provider_open_weather">Open Weather Map</string>
<string name="settings_weather_provider_weatherbit">Weatherbit.io</string> <string name="settings_weather_provider_weatherbit">Weatherbit.io</string>
<string name="settings_weather_provider_foreca">Foreca.com</string> <string name="settings_weather_provider_weather_api">Weatherapi.com</string>
<string name="settings_weather_provider_here">Here.com</string> <string name="settings_weather_provider_here">Here.com</string>
<string name="settings_weather_provider_accuweather">Accuweather.com</string> <string name="settings_weather_provider_accuweather">Accuweather.com</string>
<string name="settings_weather_provider_weather_gov">Weather.gov (US)\nPowered by National Weather Services</string> <string name="settings_weather_provider_weather_gov">Weather.gov (US)\nPowered by National Weather Services</string>
<string name="settings_weather_provider_yr">YR.no/Met.no\nPowered by Meteorological Institute</string> <string name="settings_weather_provider_yr">YR.no/Met.no\nPowered by Meteorological Institute</string>
<string name="settings_weather_provider_smhi">Smhi.se (Swedish)\nPowered by Swedish Meteorological</string>
<string name="settings_weather_provider_weather_ca">Weather.gc.ca (Canada)</string>
<string name="settings_weather_provider_bom">BOM (Australia)\nPowered by Australia\'s national weather</string>
<string name="settings_weather_provider_meteofrance">Meteofrance.com (France)</string>
<string name="action_open_provider_open_weather">Open openweathermap.com</string> <string name="action_open_provider_open_weather">Open openweathermap.com</string>
<string name="action_open_provider_weatherbit">Open weatherbit.io</string> <string name="action_open_provider_weatherbit">Open weatherbit.io</string>
<string name="action_open_provider_foreca">Open foreca.com</string> <string name="action_open_provider_weatherapi">Open weatherapi.com</string>
<string name="action_open_provider_here">Open here.com</string> <string name="action_open_provider_here">Open here.com</string>
<string name="action_open_provider_accuweather">Open Accuweather.com</string> <string name="action_open_provider_accuweather">Open Accuweather.com</string>
<string name="action_open_provider_weather_gov">Open Weather.gov</string> <string name="action_open_provider_weather_gov">Open Weather.gov</string>
<string name="action_open_provider_yr">Open yr.no</string> <string name="action_open_provider_yr">Open yr.no</string>
<string name="action_open_provider_smhi">Open smhi.se</string>
<string name="action_open_provider_weather_ca">Open weather.gc.ca</string>
<string name="action_open_provider_bom">Open bom.gov.au</string>
<string name="action_open_provider_meteofrance">Open meteofrance.com</string>
<string name="weather_provider_info_open_weather_title">This weather provider needs\nan API key to work correctly.</string> <string name="weather_provider_info_open_weather_title">This weather provider needs\nan API key to work correctly.</string>
<string name="weather_provider_info_weatherbit_title">Weatherbit.io</string> <string name="weather_provider_info_weatherbit_title">This weather provider needs\nan API key to work correctly.</string>
<string name="weather_provider_info_foreca_title">Foreca.com</string> <string name="weather_provider_info_weatherapi_title">This weather provider needs\nan API key to work correctly.</string>
<string name="weather_provider_info_here_title">Here.com</string> <string name="weather_provider_info_here_title">This weather provider needs\nan API key to work correctly.</string>
<string name="weather_provider_info_accuweather_title">Accuweather.com</string> <string name="weather_provider_info_accuweather_title">This weather provider needs\nan API key to work correctly.</string>
<string name="weather_provider_info_weather_gov_title">This weather provider works only\nfor locations inside the US.</string> <string name="weather_provider_info_weather_gov_title">This weather provider works only\nfor locations inside the US.</string>
<string name="weather_provider_info_yr_title">YR.no/Met.no\nPowered by Meteorological Institute</string> <string name="weather_provider_info_yr_title">This weather provider allows only Celsius temperatures.</string>
<string name="weather_provider_info_smhi_title">Smhi.se (Swedish)\nPowered by Swedish Meteorological</string>
<string name="weather_provider_info_weather_ca_title">Weather.gc.ca (Canada)</string>
<string name="weather_provider_info_bom_title">BOM (Australia)\nPowered by Australia\'s national weather</string>
<string name="weather_provider_info_meteofrance_title">Meteofrance.com (France)</string>
<string name="weather_provider_info_open_weather_subtitle">Please, open the provider website, create a personal account and copy here the default key.</string> <string name="weather_provider_info_open_weather_subtitle">Please, open the provider website, create a personal account and copy here the default key.</string>
<string name="weather_provider_info_weatherbit_subtitle">Weatherbit.io</string> <string name="weather_provider_info_weatherbit_subtitle">Please, open the provider website, create a personal account and copy here the default key.</string>
<string name="weather_provider_info_foreca_subtitle">Foreca.com</string> <string name="weather_provider_info_weatherapi_subtitle">Please, open the provider website, create a personal account and copy here the default key.</string>
<string name="weather_provider_info_here_subtitle">Here.com</string> <string name="weather_provider_info_here_subtitle">Please, open the provider website, create a personal account and copy here the default key.</string>
<string name="weather_provider_info_accuweather_subtitle">Accuweather.com</string> <string name="weather_provider_info_accuweather_subtitle">Please, open the provider website, create a personal account and copy here the default key.</string>
<string name="weather_provider_info_weather_gov_subtitle" /> <string name="weather_provider_info_weather_gov_subtitle" />
<string name="weather_provider_info_yr_subtitle">YR.no/Met.no\nPowered by Meteorological Institute</string> <string name="weather_provider_info_yr_subtitle" />
<string name="weather_provider_info_smhi_subtitle">Smhi.se (Swedish)\nPowered by Swedish Meteorological</string>
<string name="weather_provider_info_weather_ca_subtitle">Weather.gc.ca (Canada)</string>
<string name="weather_provider_info_bom_subtitle">BOM (Australia)\nPowered by Australia\'s national weather</string>
<string name="weather_provider_info_meteofrance_subtitle">Meteofrance.com (France)</string>
<string name="weather_provider_error_missing_key">The weather provider that you\'ve selected requires an API key.</string> <string name="weather_provider_error_missing_key">The weather provider that you\'ve selected requires an API key.</string>
<string name="weather_provider_error_wrong_location">The current location is not supported.</string> <string name="weather_provider_error_wrong_location">The current location is not supported.</string>
<string name="weather_provider_error_missing_location">Please select a valid location.</string> <string name="weather_provider_error_missing_location">Please select a valid location.</string>
<string name="weather_provider_error_expired_key">It seems that your API key has expired.</string> <string name="weather_provider_error_expired_key">It seems that your API key has expired.</string>
<string name="weather_provider_error_invalid_key">API key not valid, or not yet activated.</string>
<string name="weather_provider_error_misconfigured">The weather provider is wrongly configured.</string> <string name="weather_provider_error_misconfigured">The weather provider is wrongly configured.</string>
<!-- Clock --> <!-- Clock -->