diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 1e606d2..6db82f3 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/build.gradle b/app/build.gradle index 9546c4b..1690d0a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -112,6 +112,15 @@ dependencies { implementation "androidx.palette:palette-ktx:1.0.0" implementation 'androidx.core:core-ktx:1.3.2' + //Retrofit + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'com.google.code.gson:gson:2.8.6' + implementation 'com.squareup.retrofit2:converter-gson:2.8.1' + implementation 'com.squareup.okhttp3:logging-interceptor:3.12.0' + + //Coroutines + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5' + // Add the Firebase SDK for Crashlytics. implementation 'com.google.firebase:firebase-crashlytics:17.2.2' diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/global/Constants.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/global/Constants.kt index 14d6a91..59bb9c4 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/global/Constants.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/global/Constants.kt @@ -36,6 +36,25 @@ object Constants { HIGH(2) } + enum class WeatherProvider(val value: Int) { + OPEN_WEATHER(0), + WEATHER_BIT(1), + FORECA(2), + HERE(3), + ACCUWEATHER(4), + WEATHER_GOV(5), + YR(6), + SMHI(7), + WEATHER_CA(8), + BOM(9), + METEOFRANCE(10); + + companion object { + private val map = WeatherProvider.values().associateBy(WeatherProvider::value) + fun fromInt(type: Int) = map[type] + } + } + enum class WeatherIconPack(val value: Int) { DEFAULT(0), MINIMAL(1), diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/global/Preferences.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/global/Preferences.kt index a9ba5a3..2b927a9 100755 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/global/Preferences.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/global/Preferences.kt @@ -39,6 +39,7 @@ object Preferences : KotprefModel() { var weatherAppName by stringPref(key = "PREF_WEATHER_APP_NAME", default = "") var weatherAppPackage by stringPref(key = "PREF_WEATHER_APP_PACKAGE", default = "") var weatherProviderApi by stringPref(key = "PREF_WEATHER_PROVIDER_API_KEY", default = "") + var weatherProvider by intPref(default = Constants.WeatherProvider.OPEN_WEATHER.value) var eventAppName by stringPref(key = "PREF_EVENT_APP_NAME", default = "") var eventAppPackage by stringPref(key = "PREF_EVENT_APP_PACKAGE", default = "") var openEventDetails by booleanPref(default = true) diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/WeatherHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/WeatherHelper.kt index a08d95d..5deb694 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/WeatherHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/WeatherHelper.kt @@ -46,6 +46,22 @@ object WeatherHelper { MainWidget.updateWidget(context) } + fun getProviderName(context: Context, provider: Constants.WeatherProvider): String { + return context.getString(when(provider) { + Constants.WeatherProvider.OPEN_WEATHER -> R.string.settings_weather_provider_open_weather + Constants.WeatherProvider.WEATHER_BIT -> R.string.settings_weather_provider_weatherbit + Constants.WeatherProvider.FORECA -> R.string.settings_weather_provider_foreca + Constants.WeatherProvider.HERE -> R.string.settings_weather_provider_here + Constants.WeatherProvider.ACCUWEATHER -> R.string.settings_weather_provider_accuweather + Constants.WeatherProvider.WEATHER_GOV -> R.string.settings_weather_provider_weather_gov + 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 + }) + } + fun getWeatherIconResource(icon: String, style: Int = Preferences.weatherIconPack): Int { return when (icon) { "01d" -> { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/network/WeatherNetworkApi.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/network/WeatherNetworkApi.kt index 22481fc..d839c9d 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/network/WeatherNetworkApi.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/network/WeatherNetworkApi.kt @@ -1,19 +1,41 @@ package com.tommasoberlose.anotherwidget.network import android.content.Context +import android.util.Log +import com.google.gson.internal.LinkedTreeMap import com.kwabenaberko.openweathermaplib.constants.Units import com.kwabenaberko.openweathermaplib.implementation.OpenWeatherMapHelper import com.kwabenaberko.openweathermaplib.implementation.callbacks.CurrentWeatherCallback import com.kwabenaberko.openweathermaplib.models.currentweather.CurrentWeather +import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.helpers.WeatherHelper +import com.tommasoberlose.anotherwidget.network.repository.WeatherGovRepository import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import org.greenrobot.eventbus.EventBus +import java.lang.Exception class WeatherNetworkApi(val context: Context) { fun updateWeather() { - if (Preferences.showWeather && Preferences.weatherProviderApi != "" && Preferences.customLocationLat != "" && Preferences.customLocationLon != "") { + if (Preferences.showWeather && Preferences.customLocationLat != "" && Preferences.customLocationLon != "") { + when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) { + Constants.WeatherProvider.OPEN_WEATHER -> useOpenWeatherMap(context) + Constants.WeatherProvider.WEATHER_GOV -> useWeatherGov(context) + } + } else { + WeatherHelper.removeWeather( + context + ) + } + } + + private fun useOpenWeatherMap(context: Context) { + if (Preferences.weatherProviderApi != "" ) { val helper = OpenWeatherMapHelper(Preferences.weatherProviderApi) helper.setUnits(if (Preferences.weatherTempUnit == "F") Units.IMPERIAL else Units.METRIC) helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object : @@ -39,4 +61,27 @@ class WeatherNetworkApi(val context: Context) { ) } } + + private fun useWeatherGov(context: Context) { + CoroutineScope(Dispatchers.IO).launch { + val repository = WeatherGovRepository() + try { + val points = repository.getGridPoints( + Preferences.customLocationLat, + Preferences.customLocationLon + ) + + val pp = points["properties"] as LinkedTreeMap<*,*> + val gridId = pp["gridId"] as String + val gridX = pp["gridX"] as Double + val gridY = pp["gridY"] as Double + + val weather = repository.getWeather(gridId, gridX, gridY) + + Log.d("ciao", weather.toString()) + } catch (ex: Exception) { + Log.d("ciao", ex.localizedMessage) + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/network/api/WeatherGovApiService.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/network/api/WeatherGovApiService.kt new file mode 100644 index 0000000..ec20295 --- /dev/null +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/network/api/WeatherGovApiService.kt @@ -0,0 +1,12 @@ +package com.tommasoberlose.anotherwidget.network.api + +import retrofit2.http.GET +import retrofit2.http.Path + +interface WeatherGovApiService { + @GET("points/{latitude},{longitude}") + suspend fun getGridPoints(@Path("latitude") latitude: String, @Path("longitude") longitude: String): HashMap + + @GET("gridpoints/{gridId}/{gridX},{gridY}/forecast") + suspend fun getWeather(@Path("gridId") gridId: String, @Path("gridX") gridX: Int, @Path("gridY") gridY: Int): HashMap +} \ No newline at end of file diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/network/repository/WeatherGovRepository.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/network/repository/WeatherGovRepository.kt new file mode 100644 index 0000000..f21c44b --- /dev/null +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/network/repository/WeatherGovRepository.kt @@ -0,0 +1,23 @@ +package com.tommasoberlose.anotherwidget.network.repository + +import com.tommasoberlose.anotherwidget.network.api.WeatherGovApiService +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +class WeatherGovRepository() { + + private val apiService: WeatherGovApiService = getRetrofit().create(WeatherGovApiService::class.java) + + suspend fun getGridPoints(latitude: String, longitude: String) = apiService.getGridPoints(latitude, longitude) + suspend fun getWeather(gridId: String, gridX: Double, gridY: Double) = apiService.getWeather(gridId, gridX.toInt(), gridY.toInt()) + + companion object { + private const val BASE_URL = "https://api.weather.gov/" + private fun getRetrofit(): Retrofit { + return Retrofit.Builder() + .baseUrl(BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .build() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/WeatherTabFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/WeatherTabFragment.kt index 84dc878..cab21d0 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/WeatherTabFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/WeatherTabFragment.kt @@ -102,6 +102,12 @@ class WeatherTabFragment : Fragment() { checkLocationPermission() }) + viewModel.weatherProvider.observe(viewLifecycleOwner, Observer { + maintainScrollPosition { + label_weather_provider.text = WeatherHelper.getProviderName(requireContext(), Constants.WeatherProvider.fromInt(it)!!) + } + }) + viewModel.weatherProviderApi.observe(viewLifecycleOwner, Observer { maintainScrollPosition { checkWeatherProviderConfig() @@ -198,6 +204,21 @@ class WeatherTabFragment : Fragment() { Preferences.showWeather = enabled } + action_weather_provider.setOnClickListener { + if (Preferences.showWeather) { + val dialog = BottomSheetMenu(requireContext(), header = getString(R.string.settings_weather_provider_api)).setSelectedValue(Preferences.weatherProvider) + (0 until 11).forEach { + val item = Constants.WeatherProvider.fromInt(it) + dialog.addItem(WeatherHelper.getProviderName(requireContext(), item!!), it) + } + + dialog.addOnSelectItemListener { value -> + Preferences.weatherProvider = value + checkWeatherProviderConfig() + }.show() + } + } + action_weather_provider_api_key.setOnClickListener { if (Preferences.showWeather) { startActivityForResult( diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/viewmodels/MainViewModel.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/viewmodels/MainViewModel.kt index c6b7354..455fd29 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/viewmodels/MainViewModel.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/viewmodels/MainViewModel.kt @@ -67,6 +67,7 @@ class MainViewModel : ViewModel() { val showWeatherWarning = Preferences.asLiveData(Preferences::showWeatherWarning) val weatherIconPack = Preferences.asLiveData(Preferences::weatherIconPack) + val weatherProvider = Preferences.asLiveData(Preferences::weatherProvider) // Glance val showGlance = Preferences.asLiveData(Preferences::showGlance) diff --git a/app/src/main/res/drawable-hdpi/round_api_white_18.png b/app/src/main/res/drawable-hdpi/round_api_white_18.png new file mode 100644 index 0000000..23fb90f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/round_api_white_18.png differ diff --git a/app/src/main/res/drawable-hdpi/round_api_white_24.png b/app/src/main/res/drawable-hdpi/round_api_white_24.png new file mode 100644 index 0000000..000e4e1 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/round_api_white_24.png differ diff --git a/app/src/main/res/drawable-hdpi/round_api_white_36.png b/app/src/main/res/drawable-hdpi/round_api_white_36.png new file mode 100644 index 0000000..c50613a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/round_api_white_36.png differ diff --git a/app/src/main/res/drawable-hdpi/round_api_white_48.png b/app/src/main/res/drawable-hdpi/round_api_white_48.png new file mode 100644 index 0000000..75016f0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/round_api_white_48.png differ diff --git a/app/src/main/res/drawable-mdpi/round_api_white_18.png b/app/src/main/res/drawable-mdpi/round_api_white_18.png new file mode 100644 index 0000000..562a349 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/round_api_white_18.png differ diff --git a/app/src/main/res/drawable-mdpi/round_api_white_24.png b/app/src/main/res/drawable-mdpi/round_api_white_24.png new file mode 100644 index 0000000..b1d4a99 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/round_api_white_24.png differ diff --git a/app/src/main/res/drawable-mdpi/round_api_white_36.png b/app/src/main/res/drawable-mdpi/round_api_white_36.png new file mode 100644 index 0000000..000e4e1 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/round_api_white_36.png differ diff --git a/app/src/main/res/drawable-mdpi/round_api_white_48.png b/app/src/main/res/drawable-mdpi/round_api_white_48.png new file mode 100644 index 0000000..260f31c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/round_api_white_48.png differ diff --git a/app/src/main/res/drawable-xhdpi/round_api_white_18.png b/app/src/main/res/drawable-xhdpi/round_api_white_18.png new file mode 100644 index 0000000..000e4e1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/round_api_white_18.png differ diff --git a/app/src/main/res/drawable-xhdpi/round_api_white_24.png b/app/src/main/res/drawable-xhdpi/round_api_white_24.png new file mode 100644 index 0000000..260f31c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/round_api_white_24.png differ diff --git a/app/src/main/res/drawable-xhdpi/round_api_white_36.png b/app/src/main/res/drawable-xhdpi/round_api_white_36.png new file mode 100644 index 0000000..75016f0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/round_api_white_36.png differ diff --git a/app/src/main/res/drawable-xhdpi/round_api_white_48.png b/app/src/main/res/drawable-xhdpi/round_api_white_48.png new file mode 100644 index 0000000..849ef1c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/round_api_white_48.png differ diff --git a/app/src/main/res/drawable-xxhdpi/round_api_white_18.png b/app/src/main/res/drawable-xxhdpi/round_api_white_18.png new file mode 100644 index 0000000..c50613a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/round_api_white_18.png differ diff --git a/app/src/main/res/drawable-xxhdpi/round_api_white_24.png b/app/src/main/res/drawable-xxhdpi/round_api_white_24.png new file mode 100644 index 0000000..75016f0 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/round_api_white_24.png differ diff --git a/app/src/main/res/drawable-xxhdpi/round_api_white_36.png b/app/src/main/res/drawable-xxhdpi/round_api_white_36.png new file mode 100644 index 0000000..71d3f34 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/round_api_white_36.png differ diff --git a/app/src/main/res/drawable-xxhdpi/round_api_white_48.png b/app/src/main/res/drawable-xxhdpi/round_api_white_48.png new file mode 100644 index 0000000..87aaea4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/round_api_white_48.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/round_api_white_18.png b/app/src/main/res/drawable-xxxhdpi/round_api_white_18.png new file mode 100644 index 0000000..75016f0 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/round_api_white_18.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/round_api_white_24.png b/app/src/main/res/drawable-xxxhdpi/round_api_white_24.png new file mode 100644 index 0000000..849ef1c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/round_api_white_24.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/round_api_white_36.png b/app/src/main/res/drawable-xxxhdpi/round_api_white_36.png new file mode 100644 index 0000000..87aaea4 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/round_api_white_36.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/round_api_white_48.png b/app/src/main/res/drawable-xxxhdpi/round_api_white_48.png new file mode 100644 index 0000000..a74e7bd Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/round_api_white_48.png differ diff --git a/app/src/main/res/drawable/round_api.xml b/app/src/main/res/drawable/round_api.xml new file mode 100644 index 0000000..b44f382 --- /dev/null +++ b/app/src/main/res/drawable/round_api.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/fragment_weather_settings.xml b/app/src/main/res/layout/fragment_weather_settings.xml index c36fa61..de8d939 100644 --- a/app/src/main/res/layout/fragment_weather_settings.xml +++ b/app/src/main/res/layout/fragment_weather_settings.xml @@ -124,6 +124,44 @@ android:textColor="@color/colorAccent" android:textAppearance="@style/AnotherWidget.Settings.Header" app:textAllCaps="false" /> + + + + + + + Icon pack Icon pack %d Raccoglieremo i dati sulla posizione per attivare l\'aggiornamento del meteo anche quando l\'app รจ chiusa o non in uso.\nNon utilizzeremo i tuoi dati in nessun altro modo. + Provider meteo Orologio @@ -196,6 +197,8 @@ Setup Stile Preferenze + + Apri la privacy policy dell\'app Scegli applicazione diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1a51a4f..277e84b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -118,6 +118,18 @@ Icon pack Icon pack %d We will collect location data to update the weather information even when the app is closed or not in use.\nWe will not use these data otherwise. + Weather provider + Open Weather Map + Weatherbit.io + Foreca.com + Here.com + Accuweather.com + Weather.gov (US)\nPowered by National Weather Services + YR.no/Met.no\nPowered by Meteorological Institute + Smhi.se (Swedish)\nPowered by Swedish Meteorological + Weather.gc.ca (Canada) + BOM (Australia)\nPowered by Australia\'s national weather + Meteofrance.com (France) Clock @@ -202,6 +214,8 @@ Provider Appearance Preferences + + View the privacy policy of the app Choose application @@ -217,6 +231,4 @@ Integrations %d installed integrations Nothing - - View the privacy policy of the app \ No newline at end of file