diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index 1f71170..6d0ee1c 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 088fe52..2ceaf16 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,7 +1,6 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
- id 'kotlin-android-extensions'
id 'kotlin-kapt'
id 'androidx.navigation.safeargs'
}
@@ -13,14 +12,12 @@ def relKeyAlias = System.getenv("RELEASE_KEY_ALIAS")
def keystorePath = System.getenv('PWD') + "/app/keystore.jks"
def keystore = file(keystorePath).exists() ? file(keystorePath) : null
android {
- lintOptions {
- abortOnError false
- }
+ namespace 'com.appttude.h_mal.atlas_weather'
+ compileSdk = Integer.parseInt(TARGET_SDK_VERSION)
defaultConfig {
applicationId "com.appttude.h_mal.atlas_weather"
- compileSdk 33
- minSdkVersion 26
- targetSdkVersion 33
+ minSdkVersion MIN_SDK_VERSION
+ targetSdkVersion TARGET_SDK_VERSION
versionCode 5
versionName "3.0"
testInstrumentationRunner "com.appttude.h_mal.atlas_weather.application.TestRunner"
@@ -78,20 +75,23 @@ android {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs += [
- '-Xjvm-default=enable'
+ '-Xjvm-default=all-compatibility'
]
}
- flavorDimensions "default"
+ buildFeatures {
+ flavorDimensions = ["version"]
+ }
productFlavors {
atlasWeather {
+ dimension "version"
applicationId "com.appttude.h_mal.atlas_weather"
versionCode 5
versionName "3.0.0"
}
monoWeather {
+ dimension "version"
applicationId "com.appttude.h_mal.monoWeather"
-
versionCode 7
versionName "4.2.0"
}
@@ -108,105 +108,113 @@ android {
}
}
}
-
+ lint {
+ abortOnError false
+ }
+ testBuildType "debug"
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation 'androidx.appcompat:appcompat:1.6.1'
- implementation 'com.google.android.material:material:1.2.1'
- implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
- implementation 'androidx.fragment:fragment:1.2.0'
- implementation 'androidx.legacy:legacy-support-v4:1.0.0'
- implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
- implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
- implementation "com.google.android.gms:play-services-location:21.0.1"
- implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
- implementation 'androidx.cardview:cardview:1.0.0'
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'
- implementation 'androidx.preference:preference:1.2.1'
- testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.1'
+ implementation "androidx.appcompat:appcompat:$APP_COMPAT"
+ implementation "com.google.android.material:material:$MATERIAL_VERSION"
+ implementation "androidx.constraintlayout:constraintlayout:$CONSTR_LAYOUT_VERSION"
+ implementation "androidx.fragment:fragment:$FRAGMENT_VERSION"
+ implementation "androidx.fragment:fragment-ktx:$FRAGMENT_VERSION"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$KOTLIN_VERSION"
+ implementation "androidx.preference:preference:$PREFERENCES_VERSION"
+ implementation "androidx.core:core:$ANDROID_CORE"
+ implementation "androidx.customview:customview:$CUSTOM_VIEW"
+ implementation "androidx.cardview:cardview:$CARD_VIEW"
+ implementation "androidx.lifecycle:lifecycle-common:$ANDROID_LIFECYCLE"
+ implementation "androidx.lifecycle:lifecycle-livedata-core:$ANDROID_LIFECYCLE"
+ implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$ANDROID_LIFECYCLE"
+ implementation "androidx.lifecycle:lifecycle-viewmodel:$ANDROID_LIFECYCLE"
+ implementation "androidx.recyclerview:recyclerview:$RECYCLER_VIEW"
+ implementation "androidx.swiperefreshlayout:swiperefreshlayout:$SWIPE_REFRESH"
+ implementation "com.google.code.gson:gson:$GSON"
+ implementation "com.google.guava:guava:$GUAVA"
+ implementation 'io.reactivex.rxjava2:rxjava:2.2.0'
+ // force upgrade to 1.1.0 because its required by androidTestImplementation,
+ // and without this statement AGP will silently downgrade to tracing:1.0.0
+ implementation "androidx.tracing:tracing:1.1.0"
+ / * Google play services * /
+ implementation "com.google.android.gms:play-services-location:$GOOGLE_PLAY_SERVICE"
/ * Unit testing * /
- testImplementation 'junit:junit:4.13.2'
- androidTestImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
- testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
- implementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
- / * Fragment Navigation * /
- implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2'
- implementation 'androidx.navigation:navigation-ui-ktx:2.3.2'
+ testImplementation "junit:junit:$JUNIT_VERSION"
+ androidTestImplementation project(path: ':app')
+ testRuntimeOnly "org.jetbrains.kotlin:kotlin-test-junit:$KOTLIN_VERSION"
+ testImplementation "org.jetbrains.kotlin:kotlin-test:$KOTLIN_VERSION"
+ androidTestImplementation "junit:junit:$JUNIT_VERSION"
+ testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$KOTLINX_COROUTINES"
+ testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$KOTLINX_COROUTINES"
+ testImplementation "androidx.cardview:cardview:$CARD_VIEW"
+ testImplementation "com.tomtom.online:sdk-maps-ui-extensions:$TOMTOM_MAP"
+ / * Navigation * /
+ implementation "androidx.navigation:navigation-common:$NAVIGATION_VERSION"
+ implementation "androidx.navigation:navigation-fragment:$NAVIGATION_VERSION"
+ implementation "androidx.navigation:navigation-runtime:$NAVIGATION_VERSION"
+ implementation "androidx.navigation:navigation-ui:$NAVIGATION_VERSION"
/ * android unit testing and espresso * /
- androidTestImplementation 'androidx.test:rules:1.5.0'
- androidTestImplementation "androidx.test:core:1.5.0"
-
- / * Android Espresso * /
- def testJunitVersion = "1.1.5"
- def testRunnerVersion = "1.5.2"
- def espressoVersion = "3.5.1"
- androidTestImplementation "androidx.test.ext:junit:$testJunitVersion"
- androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
- androidTestImplementation "androidx.test.espresso.idling:idling-concurrent:$espressoVersion"
- implementation "androidx.test.espresso:espresso-idling-resource:$espressoVersion"
- androidTestImplementation "androidx.test:runner:$testRunnerVersion"
- androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"
- androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion"
- androidTestImplementation "org.hamcrest:hamcrest:2.2"
+ androidTestImplementation "androidx.test:rules:$ANDROIDX_TEST"
+ androidTestImplementation "androidx.test:core:$ANDROIDX_TEST"
+ androidTestImplementation "androidx.test:monitor:$TEST_MONITOR"
+ androidTestImplementation "androidx.test.ext:junit:$TEST_JUNIT_VERSION"
+ androidTestRuntimeOnly "org.jetbrains.kotlin:kotlin-test-junit:$KOTLIN_VERSION"
+ androidTestImplementation "androidx.test.espresso:espresso-core:$ESPRESSO_VERSION"
+ androidTestImplementation "androidx.test.espresso:espresso-idling-resource:$ESPRESSO_VERSION"
+ androidTestImplementation "androidx.test:runner:$TEST_RUNNER_VERSION"
+ androidTestImplementation "androidx.test.espresso:espresso-contrib:$ESPRESSO_VERSION"
+ androidTestImplementation "org.hamcrest:hamcrest:$HAMCREST_VERSION"
+ androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$KOTLINX_COROUTINES"
+ androidTestImplementation "androidx.cardview:cardview:$CARD_VIEW"
+ androidTestImplementation 'com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:3.1.2'
+ androidTestImplementation "com.tomtom.online:sdk-maps-ui-extensions:$TOMTOM_MAP"
+ androidTestImplementation "org.jetbrains.kotlin:kotlin-test:$KOTLIN_VERSION"
+ atlasWeatherImplementation "androidx.cardview:cardview:$CARD_VIEW"
/ * mock websever for testing retrofit responses * /
- testImplementation "com.squareup.okhttp3:mockwebserver:4.6.0"
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
-
/ * mockito and livedata testing * /
- testImplementation 'org.mockito:mockito-inline:2.13.0'
- implementation 'androidx.arch.core:core-testing:2.2.0'
-
+ testImplementation "org.mockito:mockito-inline:$MOKITO_INLINE_VERSION"
+ testImplementation "androidx.arch.core:core-testing:$CORE_TEST_VERSION"
+ androidTestImplementation "androidx.arch.core:core-testing:$CORE_TEST_VERSION"
/ * MockK * /
- def mockk_ver = "1.10.5"
- testImplementation "io.mockk:mockk:$mockk_ver"
- androidTestImplementation "io.mockk:mockk-android:$mockk_ver"
-
- / * Retrofit * /
- def retrofit_ver = "2.9.0"
- implementation "com.squareup.retrofit2:retrofit:$retrofit_ver"
- implementation "com.squareup.retrofit2:converter-gson:$retrofit_ver"
- implementation "com.squareup.okhttp3:logging-interceptor:4.9.0"
-
- / * Shared prefs * /
- def prefs_ver = "1.2.0"
- implementation "androidx.preference:preference-ktx:$prefs_ver"
-
- / *Kodein Dependency Injection * /
- def kodein_version = "6.2.1"
- implementation "org.kodein.di:kodein-di-generic-jvm:$kodein_version"
- implementation "org.kodein.di:kodein-di-framework-android-x:$kodein_version"
-
+ testImplementation "io.mockk:mockk:$MOCKK_VERSION"
+ androidTestImplementation "io.mockk:mockk-android:$MOCKK_VERSION"
+ / * Retrofit & Okhttp * /
+ implementation "com.squareup.retrofit2:retrofit:$RETROFIT_VERSION"
+ implementation "com.squareup.retrofit2:converter-gson:$RETROFIT_VERSION"
+ implementation "com.squareup.okhttp3:logging-interceptor:$OKHTTP_VERSION"
+ implementation "com.squareup.okhttp3:okhttp:$OKHTTP_VERSION"
+ / * Kodein Dependency Injection * /
+ implementation "org.kodein.di:kodein-di-generic-jvm:$KODEIN_VERSION"
+ implementation "org.kodein.di:kodein-di-framework-android-x:$KODEIN_VERSION"
+ implementation "org.kodein.di:kodein-di-core-jvm:$KODEIN_VERSION"
+ implementation "org.kodein.di:kodein-di-framework-android-core:$KODEIN_VERSION"
/ * Room database * /
- def room_version = "2.4.3"
- implementation "androidx.room:room-runtime:$room_version"
- kapt "androidx.room:room-compiler:$room_version"
- implementation "androidx.room:room-ktx:$room_version"
-
+ runtimeOnly "androidx.room:room-runtime:$ROOM_VERSION"
+ kapt "androidx.room:room-compiler:$ROOM_VERSION"
+ implementation "androidx.room:room-ktx:$ROOM_VERSION"
+ implementation "androidx.room:room-common:$ROOM_VERSION"
+ implementation 'androidx.sqlite:sqlite:2.2.0'
/ * Picasso * /
implementation 'com.squareup.picasso:picasso:2.71828'
-
/ * coroutine * /
- def coroutine_version = "1.3.9"
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine_version"
-
+ runtimeOnly "org.jetbrains.kotlinx:kotlinx-coroutines-android:$KOTLINX_COROUTINES"
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$KOTLINX_COROUTINES"
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$KOTLINX_COROUTINES"
/ * tomtom search * /
- def tomtom_version = "2.4771"
- implementation "com.tomtom.online:sdk-search:$tomtom_version"
- implementation "com.tomtom.online:sdk-maps:2.4807"
-
- / * coroutines support for firebase operations * /
- def coroutines_google_ver = "1.6.4"
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutines_google_ver"
-
+ implementation "com.tomtom.online:sdk-search:$TOMTOM_SEARCH"
+ implementation "com.tomtom.online:sdk-maps:$TOMTOM_MAP"
+ implementation "com.tomtom.online:sdk-search-core:$TOMTOM_SEARCH"
+ monoWeatherImplementation "com.tomtom.online:sdk-maps-ui-extensions:$TOMTOM_MAP"
+ implementation "com.tomtom.online:sdk-search-core:$TOMTOM_SEARCH"
/ * Picasso * /
implementation 'com.squareup.picasso:picasso:2.71828'
-
/ * screenshot library * /
androidTestImplementation 'tools.fastlane:screengrab:2.1.1'
/ * Permissions dispatcher * /
- def dispatcher_ver = "4.9.2"
- implementation "com.github.permissions-dispatcher:permissionsdispatcher:${dispatcher_ver}"
- kapt "com.github.permissions-dispatcher:permissionsdispatcher-processor:${dispatcher_ver}"
+ implementation "com.github.permissions-dispatcher:permissionsdispatcher:$PERMISSIONS_DISPATCHER"
+ kapt "com.github.permissions-dispatcher:permissionsdispatcher-processor:$PERMISSIONS_DISPATCHER"
+ implementation "com.github.permissions-dispatcher:permissionsdispatcher-annotation:$PERMISSIONS_DISPATCHER"
}
diff --git a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTest.kt b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTest.kt
index 02c3347..3069fd6 100644
--- a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTest.kt
+++ b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTest.kt
@@ -30,6 +30,7 @@ import org.junit.Before
import org.junit.Rule
import tools.fastlane.screengrab.Screengrab
import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy
+import tools.fastlane.screengrab.locale.LocaleTestRule
@Suppress("EmptyMethod")
open class BaseTest(
@@ -47,9 +48,15 @@ open class BaseTest(
@get:Rule
var permissionRule = GrantPermissionRule.grant(Manifest.permission.ACCESS_COARSE_LOCATION)
+ @get:Rule
+ var writePermissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+
@get:Rule
var snapshotRule: SnapshotRule = SnapshotRule()
+ @Rule @JvmField
+ val localeTestRule = LocaleTestRule()
+
@Before
fun setUp() {
Screengrab.setDefaultScreenshotStrategy(UiAutomatorScreenshotStrategy())
diff --git a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTestRobot.kt b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTestRobot.kt
index 8f367eb..9138bf5 100644
--- a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTestRobot.kt
+++ b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/BaseTestRobot.kt
@@ -31,7 +31,7 @@ open class BaseTestRobot {
fun goBack() = Espresso.pressBack()
- fun fillEditText(resId: Int, text: String?): ViewInteraction =
+ fun fillEditText(resId: Int, text: String): ViewInteraction =
onView(withId(resId)).perform(
ViewActions.replaceText(text),
ViewActions.closeSoftKeyboard()
@@ -129,6 +129,16 @@ open class BaseTestRobot {
)
}
+ fun clickSubViewInRecycler(
+ recyclerId: Int,
+ position: Int,
+ ) {
+ scrollToRecyclerItemByPosition(recyclerId, position)
+ ?.perform(
+ RecyclerViewActions.actionOnItemAtPosition(position, click())
+ )
+ }
+
fun checkErrorOnTextEntry(resId: Int, errorMessage: String): ViewInteraction =
onView(withId(resId)).check(matches(checkErrorMessage(errorMessage)))
diff --git a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/utils/TestUtils.kt b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/utils/TestUtils.kt
index 2305ea8..3f8bc1d 100644
--- a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/utils/TestUtils.kt
+++ b/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/utils/TestUtils.kt
@@ -13,7 +13,7 @@ fun LiveData.getOrAwaitValue(
var data: T? = null
val latch = CountDownLatch(1)
val observer = object : Observer {
- override fun onChanged(o: T?) {
+ override fun onChanged(o: T) {
data = o
latch.countDown()
this@getOrAwaitValue.removeObserver(this)
diff --git a/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt b/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt
new file mode 100644
index 0000000..2a3d363
--- /dev/null
+++ b/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt
@@ -0,0 +1,67 @@
+package com.appttude.h_mal.atlas_weather.application
+
+import androidx.room.Room
+import androidx.test.espresso.IdlingRegistry
+import androidx.test.espresso.idling.CountingIdlingResource
+import androidx.test.platform.app.InstrumentationRegistry
+import com.appttude.h_mal.atlas_weather.data.location.LocationProvider
+import com.appttude.h_mal.atlas_weather.data.location.MockLocationProvider
+import com.appttude.h_mal.atlas_weather.data.network.NetworkModule
+import com.appttude.h_mal.atlas_weather.data.network.WeatherApi
+import com.appttude.h_mal.atlas_weather.data.network.interceptors.MockingNetworkInterceptor
+import com.appttude.h_mal.atlas_weather.data.network.interceptors.NetworkConnectionInterceptor
+import com.appttude.h_mal.atlas_weather.data.network.interceptors.QueryParamsInterceptor
+import com.appttude.h_mal.atlas_weather.data.network.networkUtils.loggingInterceptor
+import com.appttude.h_mal.atlas_weather.data.room.AppDatabase
+import com.appttude.h_mal.atlas_weather.data.room.Converter
+import java.io.BufferedReader
+
+class TestAppClass : AtlasApp() {
+ private val idlingResources = CountingIdlingResource("Data_loader")
+ private val mockingNetworkInterceptor = MockingNetworkInterceptor(idlingResources)
+
+ lateinit var database: AppDatabase
+ private val locationProvider: MockLocationProvider = MockLocationProvider()
+
+ override fun onCreate() {
+ super.onCreate()
+ IdlingRegistry.getInstance().register(idlingResources)
+ }
+
+ override fun createNetworkModule(): WeatherApi {
+ return NetworkModule().invoke(
+ mockingNetworkInterceptor,
+ NetworkConnectionInterceptor(this),
+ QueryParamsInterceptor(),
+ loggingInterceptor
+ ) as WeatherApi
+ }
+
+ override fun createLocationModule(): LocationProvider {
+ return locationProvider
+ }
+
+ override fun createRoomDatabase(): AppDatabase {
+ database = Room.inMemoryDatabaseBuilder(applicationContext, AppDatabase::class.java)
+ .allowMainThreadQueries()
+ .addTypeConverter(Converter(this))
+ .build()
+ return database
+ }
+
+ fun stubUrl(url: String, rawPath: String, code: Int = 200) {
+ val iStream =
+ InstrumentationRegistry.getInstrumentation().context.assets.open("$rawPath.json")
+ val data = iStream.bufferedReader().use(BufferedReader::readText)
+ mockingNetworkInterceptor.addUrlStub(url = url, data = data, code = code)
+ }
+
+ fun removeUrlStub(url: String) {
+ mockingNetworkInterceptor.removeUrlStub(url = url)
+ }
+
+ fun stubLocation(location: String, lat: Double = 0.00, long: Double = 0.00) {
+ locationProvider.addLocationToList(location, lat, long)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/robot/FurtherInfoScreen.kt b/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/robot/FurtherInfoScreen.kt
new file mode 100644
index 0000000..6177bda
--- /dev/null
+++ b/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/robot/FurtherInfoScreen.kt
@@ -0,0 +1,35 @@
+package com.appttude.h_mal.atlas_weather.robot
+
+import com.appttude.h_mal.atlas_weather.BaseTestRobot
+import com.appttude.h_mal.atlas_weather.R
+
+fun furtherInfoScreen(func: FurtherInfoScreen.() -> Unit) = FurtherInfoScreen().apply { func() }
+class FurtherInfoScreen : BaseTestRobot() {
+ fun verifyMaxTemperature(temperature: Int) =
+ matchText(R.id.maxtemp, StringBuilder().append(temperature).append("°").toString())
+ fun verifyAverageTemperature(temperature: Int) =
+ matchText(R.id.averagetemp, StringBuilder().append(temperature).append("°").toString())
+ fun verifyMinTemperature(temperature: Int) =
+ matchText(R.id.minimumtemp, StringBuilder().append(temperature).append("°").toString())
+
+ fun verifyWindSpeed(speedText: String) =
+ matchText(R.id.windtext, speedText)
+
+ fun verifyHumidity(humidity: Int) =
+ matchText(R.id.humiditytext, humidity.toString())
+ fun verifyPrecipitation(precipitation: Int) =
+ matchText(R.id.preciptext, precipitation.toString())
+
+ fun verifyCloudCoverage(coverage: Int) =
+ matchText(R.id.cloudtext, coverage.toString())
+
+ fun verifyUvIndex(uv: Int) =
+ matchText(R.id.uvtext, uv.toString())
+ fun verifySunrise(sunrise: String) =
+ matchText(R.id.sunrisetext, sunrise)
+ fun verifySunset(sunset: String) =
+ matchText(R.id.sunsettext, sunset)
+
+ fun refresh() = pullToRefresh(R.id.swipe_refresh)
+ fun isDisplayed() = matchViewWaitFor(R.id.maxtemp)
+}
\ No newline at end of file
diff --git a/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/robot/SettingsRobot.kt b/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/robot/SettingsRobot.kt
new file mode 100644
index 0000000..a69b125
--- /dev/null
+++ b/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/robot/SettingsRobot.kt
@@ -0,0 +1,55 @@
+package com.appttude.h_mal.atlas_weather.robot
+
+import androidx.recyclerview.widget.RecyclerView.ViewHolder
+import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.action.ViewActions.click
+import androidx.test.espresso.assertion.ViewAssertions
+import androidx.test.espresso.contrib.RecyclerViewActions
+import androidx.test.espresso.matcher.RootMatchers.isDialog
+import androidx.test.espresso.matcher.ViewMatchers
+import androidx.test.espresso.matcher.ViewMatchers.withId
+import androidx.test.espresso.matcher.ViewMatchers.withText
+import com.appttude.h_mal.atlas_weather.BaseTestRobot
+import com.appttude.h_mal.atlas_weather.R
+import com.appttude.h_mal.atlas_weather.helpers.EspressoHelper.waitForView
+import com.appttude.h_mal.atlas_weather.model.types.UnitType
+
+
+fun settingsScreen(func: SettingsScreen.() -> Unit) = SettingsScreen().apply { func() }
+class SettingsScreen : BaseTestRobot() {
+
+ fun selectWeatherUnits(unitType: UnitType) {
+ onView(withId(androidx.preference.R.id.recycler_view))
+ .perform(
+ RecyclerViewActions.actionOnItem(
+ ViewMatchers.hasDescendant(withText(R.string.weather_units)),
+ click()))
+ val label = when (unitType) {
+ UnitType.METRIC -> "Metric"
+ UnitType.IMPERIAL -> "Imperial"
+ }
+
+ onView(withText(label))
+ .inRoot(isDialog())
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+ .perform(click())
+ }
+
+
+ fun verifyCurrentTemperature(temperature: Int) =
+ matchText(R.id.temp_main_4, temperature.toString())
+
+ fun verifyCurrentLocation(location: String) = matchText(R.id.location_main_4, location)
+ fun refresh() = pullToRefresh(R.id.swipe_refresh)
+
+ fun verifyUnableToRetrieve() {
+ matchText(R.id.header_text, R.string.retrieve_warning)
+ matchText(R.id.body_text, R.string.empty_retrieve_warning)
+ }
+
+ fun isDisplayed() {
+ waitForView(
+ withText("Metric")
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/robot/WeatherScreen.kt b/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/robot/WeatherScreen.kt
new file mode 100644
index 0000000..5ca9e0c
--- /dev/null
+++ b/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/robot/WeatherScreen.kt
@@ -0,0 +1,24 @@
+package com.appttude.h_mal.atlas_weather.robot
+
+import com.appttude.h_mal.atlas_weather.BaseTestRobot
+import com.appttude.h_mal.atlas_weather.R
+import com.appttude.h_mal.atlas_weather.ui.home.adapter.forecastDaily.ViewHolderForecastDaily
+
+fun weatherScreen(func: WeatherScreen.() -> Unit) = WeatherScreen().apply { func() }
+class WeatherScreen : BaseTestRobot() {
+ fun verifyCurrentTemperature(temperature: Int) =
+ matchText(R.id.temp_main_4, temperature.toString())
+
+ fun verifyCurrentLocation(location: String) = matchText(R.id.location_main_4, location)
+ fun refresh() = pullToRefresh(R.id.swipe_refresh)
+ fun isDisplayed() = matchViewWaitFor(R.id.temp_main_4)
+
+ fun verifyUnableToRetrieve() {
+ matchText(R.id.header_text, R.string.retrieve_warning)
+ matchText(R.id.body_text, R.string.empty_retrieve_warning)
+ }
+
+ fun tapDayInformationByPosition(position: Int) {
+ clickSubViewInRecycler(R.id.forecast_listview, position)
+ }
+}
\ No newline at end of file
diff --git a/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/snapshot/SnapshotCaptureTest.kt b/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/snapshot/SnapshotCaptureTest.kt
new file mode 100644
index 0000000..4eff728
--- /dev/null
+++ b/app/src/androidTestAtlasWeather/java/com/appttude/h_mal/atlas_weather/snapshot/SnapshotCaptureTest.kt
@@ -0,0 +1,50 @@
+package com.appttude.h_mal.atlas_weather.snapshot
+
+
+import android.annotation.TargetApi
+import androidx.test.filters.SmallTest
+import com.appttude.h_mal.atlas_weather.BaseTest
+import com.appttude.h_mal.atlas_weather.ui.MainActivity
+import com.appttude.h_mal.atlas_weather.utils.Stubs
+import com.appttude.h_mal.atlas_weather.robot.furtherInfoScreen
+import com.appttude.h_mal.atlas_weather.robot.settingsScreen
+import com.appttude.h_mal.atlas_weather.robot.weatherScreen
+import org.junit.Test
+import tools.fastlane.screengrab.Screengrab
+
+@SmallTest
+@TargetApi(27)
+class SnapshotCaptureTest : BaseTest(MainActivity::class.java) {
+
+ override fun beforeLaunch() {
+ stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Metric)
+ stubLocation("London", 51.51, -0.13)
+ clearPrefs()
+ }
+
+ @Test
+ fun homeAndFurtherInfoPageCapture() {
+ weatherScreen {
+ isDisplayed()
+ Screengrab.screenshot("HomeScreen")
+ tapDayInformationByPosition(4)
+ }
+ furtherInfoScreen {
+ isDisplayed()
+ Screengrab.screenshot("FurtherInfoScreen")
+ }
+
+ }
+
+ @Test
+ fun settingsPageCapture() {
+ weatherScreen {
+ isDisplayed()
+ openMenuItem()
+ }
+ settingsScreen {
+ stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Imperial)
+ Screengrab.screenshot("SettingsScreen")
+ }
+ }
+}
diff --git a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt
similarity index 91%
rename from app/src/androidTest/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt
rename to app/src/androidTestMonoWeather/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt
index 1118703..9d796e1 100644
--- a/app/src/androidTest/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt
+++ b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/atlas_weather/application/TestAppClass.kt
@@ -16,12 +16,12 @@ import com.appttude.h_mal.atlas_weather.data.room.AppDatabase
import com.appttude.h_mal.atlas_weather.data.room.Converter
import java.io.BufferedReader
-class TestAppClass : BaseAppClass() {
+class TestAppClass : MonoApp() {
private val idlingResources = CountingIdlingResource("Data_loader")
private val mockingNetworkInterceptor = MockingNetworkInterceptor(idlingResources)
lateinit var database: AppDatabase
- lateinit var locationProvider: MockLocationProvider
+ private val locationProvider: MockLocationProvider = MockLocationProvider()
override fun onCreate() {
super.onCreate()
@@ -38,12 +38,12 @@ class TestAppClass : BaseAppClass() {
}
override fun createLocationModule(): LocationProvider {
- locationProvider = MockLocationProvider()
return locationProvider
}
override fun createRoomDatabase(): AppDatabase {
- database = Room.inMemoryDatabaseBuilder(this, AppDatabase::class.java)
+ database = Room.inMemoryDatabaseBuilder(applicationContext, AppDatabase::class.java)
+ .allowMainThreadQueries()
.addTypeConverter(Converter(this))
.build()
return database
diff --git a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/atlas_weather/snapshot/SnapshotCaptureTest.kt b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/atlas_weather/snapshot/SnapshotCaptureTest.kt
new file mode 100644
index 0000000..a5e17bc
--- /dev/null
+++ b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/atlas_weather/snapshot/SnapshotCaptureTest.kt
@@ -0,0 +1,51 @@
+package com.appttude.h_mal.atlas_weather.snapshot
+
+
+import android.annotation.TargetApi
+import androidx.test.filters.SmallTest
+import com.appttude.h_mal.atlas_weather.BaseTest
+import com.appttude.h_mal.atlas_weather.ui.MainActivity
+import com.appttude.h_mal.atlas_weather.utils.Stubs
+import com.appttude.h_mal.monoWeather.robot.furtherInfoScreen
+import com.appttude.h_mal.monoWeather.robot.settingsScreen
+import com.appttude.h_mal.monoWeather.robot.weatherScreen
+import org.junit.Test
+import tools.fastlane.screengrab.Screengrab
+
+@SmallTest
+@TargetApi(27)
+class SnapshotCaptureTest : BaseTest(MainActivity::class.java) {
+
+ override fun beforeLaunch() {
+ stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Metric)
+ stubLocation("London", 51.51, -0.13)
+ clearPrefs()
+ }
+
+
+ @Test
+ fun homeAndFurtherInfoPageCapture() {
+ weatherScreen {
+ isDisplayed()
+ Screengrab.screenshot("HomeScreen")
+ tapDayInformationByPosition(4)
+ }
+ furtherInfoScreen {
+ isDisplayed()
+ Screengrab.screenshot("FurtherInfoScreen")
+ }
+
+ }
+
+ @Test
+ fun settingsPageCapture() {
+ weatherScreen {
+ isDisplayed()
+ openMenuItem()
+ }
+ settingsScreen {
+ stubEndpoint("https://api.openweathermap.org/data/2.5/onecall", Stubs.Imperial)
+ Screengrab.screenshot("SettingsScreen")
+ }
+ }
+}
diff --git a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/FurtherInfoScreen.kt b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/FurtherInfoScreen.kt
new file mode 100644
index 0000000..39d413b
--- /dev/null
+++ b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/FurtherInfoScreen.kt
@@ -0,0 +1,37 @@
+package com.appttude.h_mal.monoWeather.robot
+
+import com.appttude.h_mal.atlas_weather.BaseTestRobot
+import com.appttude.h_mal.atlas_weather.R
+import com.appttude.h_mal.monoWeather.ui.home.adapter.forecastDaily.ViewHolderForecastDaily
+import com.appttude.h_mal.monoWeather.ui.home.adapter.further.ViewHolderFurtherDetails
+
+fun furtherInfoScreen(func: FurtherInfoScreen.() -> Unit) = FurtherInfoScreen().apply { func() }
+class FurtherInfoScreen : BaseTestRobot() {
+ fun verifyMaxTemperature(temperature: Int) =
+ matchText(R.id.maxtemp, StringBuilder().append(temperature).append("°").toString())
+ fun verifyAverageTemperature(temperature: Int) =
+ matchText(R.id.averagetemp, StringBuilder().append(temperature).append("°").toString())
+ fun verifyMinTemperature(temperature: Int) =
+ matchText(R.id.minimumtemp, StringBuilder().append(temperature).append("°").toString())
+
+ fun verifyWindSpeed(speedText: String) =
+ matchText(R.id.windtext, speedText)
+
+ fun verifyHumidity(humidity: Int) =
+ matchText(R.id.humiditytext, humidity.toString())
+ fun verifyPrecipitation(precipitation: Int) =
+ matchText(R.id.preciptext, precipitation.toString())
+
+ fun verifyCloudCoverage(coverage: Int) =
+ matchText(R.id.cloudtext, coverage.toString())
+
+ fun verifyUvIndex(uv: Int) =
+ matchText(R.id.uvtext, uv.toString())
+ fun verifySunrise(sunrise: String) =
+ matchText(R.id.sunrisetext, sunrise)
+ fun verifySunset(sunset: String) =
+ matchText(R.id.sunsettext, sunset)
+
+ fun refresh() = pullToRefresh(R.id.swipe_refresh)
+ fun isDisplayed() = matchViewWaitFor(R.id.maxtemp)
+}
\ No newline at end of file
diff --git a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/SettingsRobot.kt b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/SettingsRobot.kt
index ee50ee6..c69c4df 100644
--- a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/SettingsRobot.kt
+++ b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/SettingsRobot.kt
@@ -11,6 +11,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import com.appttude.h_mal.atlas_weather.BaseTestRobot
import com.appttude.h_mal.atlas_weather.R
+import com.appttude.h_mal.atlas_weather.helpers.EspressoHelper.waitForView
import com.appttude.h_mal.atlas_weather.model.types.UnitType
@@ -45,4 +46,10 @@ class SettingsScreen : BaseTestRobot() {
matchText(R.id.header_text, R.string.retrieve_warning)
matchText(R.id.body_text, R.string.empty_retrieve_warning)
}
+
+ fun isDisplayed() {
+ waitForView(
+ withText("Metric")
+ )
+ }
}
\ No newline at end of file
diff --git a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/WeatherScreen.kt b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/WeatherScreen.kt
index 7f4034f..322b634 100644
--- a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/WeatherScreen.kt
+++ b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/robot/WeatherScreen.kt
@@ -2,6 +2,8 @@ package com.appttude.h_mal.monoWeather.robot
import com.appttude.h_mal.atlas_weather.BaseTestRobot
import com.appttude.h_mal.atlas_weather.R
+import com.appttude.h_mal.monoWeather.ui.home.adapter.forecastDaily.ViewHolderForecastDaily
+import com.appttude.h_mal.monoWeather.ui.home.adapter.further.ViewHolderFurtherDetails
fun weatherScreen(func: WeatherScreen.() -> Unit) = WeatherScreen().apply { func() }
class WeatherScreen : BaseTestRobot() {
@@ -16,4 +18,8 @@ class WeatherScreen : BaseTestRobot() {
matchText(R.id.header_text, R.string.retrieve_warning)
matchText(R.id.body_text, R.string.empty_retrieve_warning)
}
+
+ fun tapDayInformationByPosition(position: Int) {
+ clickSubViewInRecycler(R.id.forecast_listview, position)
+ }
}
\ No newline at end of file
diff --git a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/tests/HomePageNoDataUITest.kt b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/tests/HomePageNoDataUITest.kt
index 2bbe172..97a17d1 100644
--- a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/tests/HomePageNoDataUITest.kt
+++ b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/tests/HomePageNoDataUITest.kt
@@ -5,6 +5,7 @@ import com.appttude.h_mal.atlas_weather.BaseTest
import com.appttude.h_mal.atlas_weather.ui.MainActivity
import com.appttude.h_mal.atlas_weather.utils.Stubs
import com.appttude.h_mal.monoWeather.robot.weatherScreen
+import org.junit.Ignore
import org.junit.Test
class HomePageNoDataUITest : BaseTest(MainActivity::class.java) {
@@ -21,6 +22,7 @@ class HomePageNoDataUITest : BaseTest(MainActivity::class.java) {
}
}
+ @Ignore("Test is flakey - must investigate")
@Test
fun invalidKeyWeatherResponse_swipeToRefresh_returnsValidPage() {
weatherScreen {
diff --git a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/tests/HomePageUITest.kt b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/tests/HomePageUITest.kt
index 1bc556e..fbe8e39 100644
--- a/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/tests/HomePageUITest.kt
+++ b/app/src/androidTestMonoWeather/java/com/appttude/h_mal/monoWeather/tests/HomePageUITest.kt
@@ -5,9 +5,11 @@ import com.appttude.h_mal.atlas_weather.BaseTest
import com.appttude.h_mal.atlas_weather.model.types.UnitType
import com.appttude.h_mal.atlas_weather.ui.MainActivity
import com.appttude.h_mal.atlas_weather.utils.Stubs
+import com.appttude.h_mal.monoWeather.robot.furtherInfoScreen
import com.appttude.h_mal.monoWeather.robot.settingsScreen
import com.appttude.h_mal.monoWeather.robot.weatherScreen
import org.junit.Test
+import tools.fastlane.screengrab.Screengrab
class HomePageUITest : BaseTest(MainActivity::class.java) {
@@ -25,6 +27,22 @@ class HomePageUITest : BaseTest(MainActivity::class.java) {
}
}
+ @Test
+ fun loadApp_validWeatherResponse_viewFurtherDetailsPage() {
+ weatherScreen {
+ isDisplayed()
+ verifyCurrentTemperature(2)
+ verifyCurrentLocation("Mock Location")
+ tapDayInformationByPosition(4)
+ }
+ furtherInfoScreen {
+ isDisplayed()
+ verifyMaxTemperature(12)
+ verifyAverageTemperature(9)
+ }
+
+ }
+
@Test
fun loadApp_changeToImperial_returnsValidPage() {
weatherScreen {
diff --git a/app/src/atlasWeather/AndroidManifest.xml b/app/src/atlasWeather/AndroidManifest.xml
index c4aa1c8..bb3fd3e 100644
--- a/app/src/atlasWeather/AndroidManifest.xml
+++ b/app/src/atlasWeather/AndroidManifest.xml
@@ -2,8 +2,10 @@
+
+
-
-
-
-
-
-
-
-
-
-
+ android:name=".service.notification.NotificationReceiver"
+ android:exported="false"/>
diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/application/ApplicationViewModelFactory.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/application/ApplicationViewModelFactory.kt
new file mode 100644
index 0000000..814d62f
--- /dev/null
+++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/application/ApplicationViewModelFactory.kt
@@ -0,0 +1,46 @@
+package com.appttude.h_mal.atlas_weather.application
+
+import android.app.Application
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.appttude.h_mal.atlas_weather.data.WeatherSource
+import com.appttude.h_mal.atlas_weather.data.location.LocationProvider
+import com.appttude.h_mal.atlas_weather.data.repository.SettingsRepository
+import com.appttude.h_mal.atlas_weather.service.notification.NotificationService
+import com.appttude.h_mal.atlas_weather.viewmodel.MainViewModel
+import com.appttude.h_mal.atlas_weather.viewmodel.SettingsViewModel
+import com.appttude.h_mal.atlas_weather.viewmodel.WorldViewModel
+
+
+class ApplicationViewModelFactory(
+ private val application: Application,
+ private val locationProvider: LocationProvider,
+ private val source: WeatherSource,
+ private val settingsRepository: SettingsRepository,
+ private val notificationService: NotificationService
+) : ViewModelProvider.Factory {
+
+ @Suppress("UNCHECKED_CAST")
+ override fun create(modelClass: Class): T {
+ with(modelClass) {
+ return when {
+ isAssignableFrom(WorldViewModel::class.java) -> WorldViewModel(
+ locationProvider,
+ source
+ )
+
+ isAssignableFrom(MainViewModel::class.java) -> MainViewModel(
+ locationProvider,
+ source
+ )
+
+ isAssignableFrom(SettingsViewModel::class.java) -> SettingsViewModel(
+ application, locationProvider, source, settingsRepository, notificationService
+ )
+
+ else -> throw IllegalArgumentException("Unknown ViewModel class")
+ } as T
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/application/AtlasApp.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/application/AtlasApp.kt
new file mode 100644
index 0000000..0b939fd
--- /dev/null
+++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/application/AtlasApp.kt
@@ -0,0 +1,46 @@
+package com.appttude.h_mal.atlas_weather.application
+
+import com.appttude.h_mal.atlas_weather.service.notification.NotificationHelper
+import com.appttude.h_mal.atlas_weather.service.notification.NotificationService
+import org.kodein.di.generic.bind
+import org.kodein.di.generic.instance
+import org.kodein.di.generic.provider
+import org.kodein.di.generic.singleton
+
+
+open class AtlasApp : AppClass() {
+
+ private lateinit var notificationService: NotificationService
+
+ override val flavourModule = super.flavourModule.copy {
+ bind() from singleton {
+ NotificationHelper(
+ instance(),
+ instance(),
+ )
+ }
+
+ bind() from singleton {
+ NotificationService(this@AtlasApp).apply { notificationService = this }
+ }
+
+ bind() from provider {
+ ApplicationViewModelFactory(
+ this@AtlasApp,
+ instance(),
+ instance(),
+ instance(),
+ instance()
+ )
+ }
+ }
+
+// override fun onCreate() {
+// super.onCreate()
+// notificationService.schedulePushNotifications()
+// }
+
+ fun scheduleNotifications() = notificationService.schedulePushNotifications()
+
+ fun unscheduleNotifications() = notificationService.unschedulePushNotifications()
+}
\ No newline at end of file
diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/notification/NotificationData.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/notification/NotificationData.kt
deleted file mode 100644
index ba469d4..0000000
--- a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/notification/NotificationData.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.appttude.h_mal.atlas_weather.notification
-
-import android.graphics.Bitmap
-
-data class NotificationData(
- val temp: String,
- val icon: Bitmap
-)
\ No newline at end of file
diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/notification/NotificationReceiver.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/notification/NotificationReceiver.kt
deleted file mode 100644
index 60906b4..0000000
--- a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/notification/NotificationReceiver.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.appttude.h_mal.atlas_weather.notification
-
-import android.Manifest
-import android.app.Notification
-import android.app.NotificationManager
-import android.app.PendingIntent
-import android.app.TaskStackBuilder
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.pm.PackageManager
-import android.os.Build
-import androidx.core.app.ActivityCompat
-import com.appttude.h_mal.atlas_weather.R
-import com.appttude.h_mal.atlas_weather.ui.MainActivity
-import com.appttude.h_mal.atlas_weather.helper.ServicesHelper
-import com.appttude.h_mal.atlas_weather.model.weather.FullWeather
-import com.appttude.h_mal.atlas_weather.utils.displayToast
-import org.kodein.di.KodeinAware
-import org.kodein.di.LateInitKodein
-import org.kodein.di.generic.instance
-
-/**
- * Created by h_mal on 29/04/2018.
- * Updated by h_mal on 27/11/2020
- */
-const val NOTIFICATION_CHANNEL_ID = "my_notification_channel_1"
-
-class NotificationReceiver : BroadcastReceiver() {
-
- private val kodein = LateInitKodein()
- private val helper: ServicesHelper by kodein.instance()
-
- override fun onReceive(context: Context, intent: Intent) {
- kodein.baseKodein = (context.applicationContext as KodeinAware).kodein
-
- if (ActivityCompat.checkSelfPermission(
- context,
- Manifest.permission.ACCESS_COARSE_LOCATION
- ) != PackageManager.PERMISSION_GRANTED
- ) {
- context.displayToast("Please enable location permissions")
- return
- }
-
- // notification validation
- }
-
- private fun pushNotif(context: Context?, weather: FullWeather) {
- val notificationIntent = Intent(context, MainActivity::class.java)
-
- val stackBuilder = TaskStackBuilder.create(context).apply {
- addParentStack(MainActivity::class.java)
- addNextIntent(notificationIntent)
- }
-
- val pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
-
- val builder = Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
-
- val notification = builder.setContentTitle("Weather App")
- .setContentText(weather.current?.main + "°C")
- .setSmallIcon(R.mipmap.ic_notif) //change icon
-// .setLargeIcon(Icon.createWithResource(context, getImageResource(forecastItem.getCurrentForecast().getIconURL(), context)))
- .setAutoCancel(true)
- .setContentIntent(pendingIntent).build()
- builder.setChannelId(NOTIFICATION_CHANNEL_ID)
- val notificationManager =
- context!!.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
- notificationManager.notify(0, notification)
- }
-}
\ No newline at end of file
diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/service/notification/NotificationHelper.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/service/notification/NotificationHelper.kt
new file mode 100644
index 0000000..5541d06
--- /dev/null
+++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/service/notification/NotificationHelper.kt
@@ -0,0 +1,26 @@
+package com.appttude.h_mal.atlas_weather.service.notification
+
+import android.Manifest
+import androidx.annotation.RequiresPermission
+import com.appttude.h_mal.atlas_weather.data.WeatherSource
+import com.appttude.h_mal.atlas_weather.data.location.LocationProvider
+import com.appttude.h_mal.atlas_weather.model.weather.FullWeather
+
+class NotificationHelper(
+ private val weatherSource: WeatherSource,
+ private val locationProvider: LocationProvider
+) {
+
+ @RequiresPermission(value = Manifest.permission.ACCESS_COARSE_LOCATION)
+ suspend fun fetchData(): FullWeather? {
+ return try {
+ // Get location
+ val latLong = locationProvider.getCurrentLatLong()
+ weatherSource.getWeather(latLon = latLong)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ null
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/service/notification/NotificationReceiver.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/service/notification/NotificationReceiver.kt
new file mode 100644
index 0000000..91f88b7
--- /dev/null
+++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/service/notification/NotificationReceiver.kt
@@ -0,0 +1,117 @@
+package com.appttude.h_mal.atlas_weather.service.notification
+
+import android.Manifest
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.app.TaskStackBuilder
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.Bitmap
+import androidx.annotation.RequiresPermission
+import androidx.core.app.ActivityCompat
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import com.appttude.h_mal.atlas_weather.R
+import com.appttude.h_mal.atlas_weather.ui.MainActivity
+import com.appttude.h_mal.atlas_weather.utils.displayToast
+import com.squareup.picasso.Picasso
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import org.kodein.di.KodeinAware
+import org.kodein.di.LateInitKodein
+import org.kodein.di.generic.instance
+
+
+/**
+ * Created by h_mal on 29/04/2018.
+ * Updated by h_mal on 27/11/2020
+ */
+const val NOTIFICATION_CHANNEL_ID = "my_notification_channel_1"
+const val NOTIFICATION_ID = 505
+class NotificationReceiver : BroadcastReceiver() {
+
+
+ private val kodein = LateInitKodein()
+ private val helper: NotificationHelper by kodein.instance()
+
+ override fun onReceive(context: Context, intent: Intent) {
+ kodein.baseKodein = (context.applicationContext as KodeinAware).kodein
+
+ if (ActivityCompat.checkSelfPermission(
+ context,
+ Manifest.permission.ACCESS_COARSE_LOCATION
+ ) == PackageManager.PERMISSION_GRANTED
+ ) {
+ pushNotification(context)
+ } else {
+ context.displayToast("Please enable location permissions")
+ }
+ }
+
+ @RequiresPermission(value = Manifest.permission.ACCESS_COARSE_LOCATION)
+ private fun pushNotification(context: Context) {
+ CoroutineScope(Dispatchers.IO).launch {
+ // Retrieve weather data
+ val weather = runBlocking { helper.fetchData() } ?: return@launch
+
+ // Build notification
+ val notificationIntent = Intent(context, MainActivity::class.java)
+
+ val stackBuilder = TaskStackBuilder.create(context).apply {
+ addParentStack(MainActivity::class.java)
+ addNextIntent(notificationIntent)
+ }
+ val pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
+ val bmp: Bitmap = runBlocking { Picasso.get().load(weather.current?.icon).get() }
+
+ val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
+ .setSmallIcon(R.mipmap.ic_notif)
+ .setLargeIcon(bmp)
+ .setContentIntent(pendingIntent)
+ .setAutoCancel(true)
+ .setContentTitle("My notification")
+ .setContentText("Much longer text that cannot fit one line...")
+ .setStyle(NotificationCompat.BigTextStyle()
+ .bigText("Much longer text that cannot fit one line..."))
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+
+ // Create the NotificationChannel, but only on API 26+ because
+ // the NotificationChannel class is not in the Support Library.
+ val name = context.getString(R.string.channel_name)
+ val descriptionText = context.getString(R.string.channel_description)
+ val importance = NotificationManager.IMPORTANCE_DEFAULT
+ val channel = NotificationChannel(NOTIFICATION_CHANNEL_ID, name, importance).apply {
+ description = descriptionText
+ }
+ // Register the channel with the system.
+ val notificationManager: NotificationManager =
+ context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ notificationManager.createNotificationChannel(channel)
+
+ with(NotificationManagerCompat.from(context)) {
+ if (ActivityCompat.checkSelfPermission(
+ context,
+ Manifest.permission.POST_NOTIFICATIONS
+ ) != PackageManager.PERMISSION_GRANTED
+ ) {
+ // TODO: Consider calling
+ // ActivityCompat#requestPermissions
+ // here to request the missing permissions, and then overriding
+ // public fun onRequestPermissionsResult(requestCode: Int, permissions: Array,
+ // grantResults: IntArray)
+ // to handle the case where the user grants the permission. See the documentation
+ // for ActivityCompat#requestPermissions for more details.
+
+ return@with
+ }
+ // notificationId is a unique int for each notification that you must define.
+ notify(NOTIFICATION_ID, builder.build())
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/service/notification/NotificationService.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/service/notification/NotificationService.kt
new file mode 100644
index 0000000..b69911c
--- /dev/null
+++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/service/notification/NotificationService.kt
@@ -0,0 +1,65 @@
+package com.appttude.h_mal.atlas_weather.service.notification
+
+import android.app.AlarmManager
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Context.ALARM_SERVICE
+import android.content.Intent
+import android.icu.util.Calendar
+import android.icu.util.GregorianCalendar
+import androidx.core.app.NotificationManagerCompat
+
+
+class NotificationService(context: Context) {
+
+ private val alarmManager = context.getSystemService(ALARM_SERVICE) as AlarmManager
+ private val alarmPendingIntent by lazy {
+ val intent = Intent(context, NotificationReceiver::class.java)
+ PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
+ }
+
+ private val notificationManager = NotificationManagerCompat.from(context)
+
+ fun schedulePushNotifications() {
+ val calendar = getCalendarForNotification()
+
+ alarmManager.setWindow(
+ AlarmManager.RTC_WAKEUP,
+ calendar.timeInMillis,
+ AlarmManager.INTERVAL_HOUR,
+ alarmPendingIntent
+ )
+ }
+
+ fun unschedulePushNotifications() {
+ alarmManager.cancel(alarmPendingIntent)
+ }
+
+ fun areNotificationsEnabled() = when {
+ notificationManager.areNotificationsEnabled().not() -> false
+ else -> {
+ notificationManager.notificationChannels.firstOrNull { channel ->
+ channel.importance == NotificationManager.IMPORTANCE_NONE
+ } == null
+ }
+ }
+
+ private fun getCalendarForNotification(): Calendar {
+// return GregorianCalendar.getInstance().apply {
+// if (get(Calendar.HOUR_OF_DAY) >= HOUR_TO_SHOW_PUSH) {
+// add(Calendar.DAY_OF_MONTH, 1)
+// }
+//
+// set(Calendar.HOUR_OF_DAY, HOUR_TO_SHOW_PUSH)
+// set(Calendar.MINUTE, 0)
+// set(Calendar.SECOND, 0)
+// set(Calendar.MILLISECOND, 0)
+// }
+
+ return GregorianCalendar.getInstance().apply {
+// add(Calendar.MINUTE, 1)
+ add(Calendar.SECOND, 10)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/WorldItemFragment.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/WorldItemFragment.kt
index 49a23f0..475bd6b 100644
--- a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/WorldItemFragment.kt
+++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/WorldItemFragment.kt
@@ -6,11 +6,12 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
import com.appttude.h_mal.atlas_weather.R
import com.appttude.h_mal.atlas_weather.model.forecast.WeatherDisplay
import com.appttude.h_mal.atlas_weather.ui.home.adapter.WeatherRecyclerAdapter
import com.appttude.h_mal.atlas_weather.utils.navigateTo
-import kotlinx.android.synthetic.main.fragment_home.*
+
class WorldItemFragment : Fragment() {
@@ -40,7 +41,7 @@ class WorldItemFragment : Fragment() {
param1?.let { recyclerAdapter.addCurrent(it) }
- forecast_listview.apply {
+ view.findViewById(R.id.forecast_listview).apply {
layoutManager = LinearLayoutManager(context)
adapter = recyclerAdapter
}
diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/details/FurtherInfoFragment.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/details/FurtherInfoFragment.kt
index 18e8370..0652bba 100644
--- a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/details/FurtherInfoFragment.kt
+++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/details/FurtherInfoFragment.kt
@@ -4,10 +4,11 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.TextView
import androidx.fragment.app.Fragment
import com.appttude.h_mal.atlas_weather.R
import com.appttude.h_mal.atlas_weather.model.forecast.Forecast
-import kotlinx.android.synthetic.main.activity_further_info.*
+
private const val WEATHER = "param1"
@@ -36,14 +37,12 @@ class FurtherInfoFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- maxtemp.text = param1?.mainTemp
- averagetemp.text = param1?.averageTemp
- minimumtemp.text = param1?.minorTemp
- windtext.text = param1?.windText
- preciptext.text = param1?.precipitation
- humiditytext.text = param1?.humidity
- uvtext.text = param1?.uvi
- sunrisetext.text = param1?.sunrise
- sunsettext.text = param1?.sunset
+ view.findViewById(R.id.maxtemp).text = param1?.mainTemp
+ view.findViewById(R.id.averagetemp).text = param1?.averageTemp
+ view.findViewById(R.id.minimumtemp).text = param1?.minorTemp
+ view.findViewById(R.id.windtext).text = param1?.windText
+ view.findViewById(R.id.preciptext).text = param1?.precipitation
+ view.findViewById(R.id.sunrisetext).text = param1?.sunrise
+ view.findViewById(R.id.sunsettext).text = param1?.sunset
}
}
\ No newline at end of file
diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/home/HomeFragment.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/home/HomeFragment.kt
index baf1ae3..0785554 100644
--- a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/home/HomeFragment.kt
+++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/home/HomeFragment.kt
@@ -1,7 +1,9 @@
package com.appttude.h_mal.atlas_weather.ui.home
import android.Manifest.permission.ACCESS_COARSE_LOCATION
+import android.Manifest.permission.POST_NOTIFICATIONS
import android.annotation.SuppressLint
+import android.os.Build
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
@@ -10,9 +12,10 @@ import android.view.View
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation.findNavController
import androidx.navigation.ui.onNavDestinationSelected
-import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.appttude.h_mal.atlas_weather.R
-import com.appttude.h_mal.atlas_weather.application.LOCATION_PERMISSION_REQUEST
+import com.appttude.h_mal.atlas_weather.application.AtlasApp
import com.appttude.h_mal.atlas_weather.base.BaseFragment
import com.appttude.h_mal.atlas_weather.model.forecast.Forecast
import com.appttude.h_mal.atlas_weather.model.forecast.WeatherDisplay
@@ -21,7 +24,7 @@ import com.appttude.h_mal.atlas_weather.ui.home.adapter.WeatherRecyclerAdapter
import com.appttude.h_mal.atlas_weather.utils.displayToast
import com.appttude.h_mal.atlas_weather.utils.navigateTo
import com.appttude.h_mal.atlas_weather.viewmodel.MainViewModel
-import kotlinx.android.synthetic.main.fragment_home.*
+
import permissions.dispatcher.NeedsPermission
import permissions.dispatcher.OnNeverAskAgain
import permissions.dispatcher.OnPermissionDenied
@@ -37,14 +40,15 @@ import permissions.dispatcher.RuntimePermissions
@RuntimePermissions
class HomeFragment : BaseFragment(R.layout.fragment_home) {
- lateinit var recyclerAdapter: WeatherRecyclerAdapter
+ private lateinit var recyclerAdapter: WeatherRecyclerAdapter
+ private lateinit var swipeRefresh: SwipeRefreshLayout
@SuppressLint("MissingPermission")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
- swipe_refresh.apply {
+ swipeRefresh = view.findViewById(R.id.swipe_refresh).apply {
setOnRefreshListener {
showLocationWithPermissionCheck()
isRefreshing = true
@@ -55,7 +59,9 @@ class HomeFragment : BaseFragment(R.layout.fragment_home) {
navigateToFurtherDetails(it)
})
- forecast_listview.adapter = recyclerAdapter
+ view.findViewById(R.id.forecast_listview).adapter = recyclerAdapter
+
+ scheduleNotification()
}
@SuppressLint("MissingPermission")
@@ -66,7 +72,7 @@ class HomeFragment : BaseFragment(R.layout.fragment_home) {
override fun onSuccess(data: Any?) {
super.onSuccess(data)
- swipe_refresh.isRefreshing = false
+ swipeRefresh.isRefreshing = false
if (data is WeatherDisplay) {
recyclerAdapter.addCurrent(data)
@@ -75,7 +81,7 @@ class HomeFragment : BaseFragment(R.layout.fragment_home) {
override fun onFailure(error: Any?) {
super.onFailure(error)
- swipe_refresh.isRefreshing = false
+ swipeRefresh.isRefreshing = false
}
private fun navigateToFurtherDetails(forecast: Forecast) {
@@ -93,12 +99,21 @@ class HomeFragment : BaseFragment(R.layout.fragment_home) {
return item.onNavDestinationSelected(navController) || super.onOptionsItemSelected(item)
}
+ @Deprecated("Deprecated in Java")
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
// NOTE: delegate the permission handling to generated method
onRequestPermissionsResult(requestCode, grantResults)
}
+ fun scheduleNotification() {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+ sendNotification()
+ } else {
+ (requireActivity().application as AtlasApp).scheduleNotifications()
+ }
+ }
+
@SuppressLint("MissingPermission")
@NeedsPermission(ACCESS_COARSE_LOCATION)
fun showLocation() {
@@ -123,4 +138,29 @@ class HomeFragment : BaseFragment(R.layout.fragment_home) {
fun onLocationNeverAskAgain() {
displayToast("Location permissions have been to never ask again")
}
+
+ @SuppressLint("MissingPermission")
+ @NeedsPermission(POST_NOTIFICATIONS)
+ fun sendNotification() {
+ (requireActivity().application as AtlasApp).scheduleNotifications()
+ }
+
+ @OnShowRationale(POST_NOTIFICATIONS)
+ fun showRationaleForNotification(request: PermissionRequest) {
+// PermissionsDeclarationDialog(requireContext()).showDialog({
+// request.proceed()
+// }, {
+// request.cancel()
+// })
+ }
+
+ @OnPermissionDenied(POST_NOTIFICATIONS)
+ fun onNotificationDenied() {
+ displayToast("Notification permissions have been denied")
+ }
+
+ @OnNeverAskAgain(POST_NOTIFICATIONS)
+ fun onNotificationNeverAskAgain() {
+ displayToast("Notification permissions have been to never ask again")
+ }
}
\ No newline at end of file
diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/settings/SettingsFragment.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/settings/SettingsFragment.kt
index e8efbc1..8f0c168 100644
--- a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/settings/SettingsFragment.kt
+++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/settings/SettingsFragment.kt
@@ -1,73 +1,61 @@
package com.appttude.h_mal.atlas_weather.ui.settings
-import android.app.AlarmManager
-import android.app.PendingIntent
-import android.appwidget.AppWidgetManager
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.os.Bundle
-import androidx.preference.PreferenceFragmentCompat
-import androidx.preference.PreferenceManager
import com.appttude.h_mal.atlas_weather.R
-import com.appttude.h_mal.atlas_weather.notification.NotificationReceiver
-import com.appttude.h_mal.atlas_weather.widget.NewAppWidget
-import java.util.Calendar
+import com.appttude.h_mal.atlas_weather.base.BasePreferencesFragment
+import com.appttude.h_mal.atlas_weather.utils.displayToast
+import com.appttude.h_mal.atlas_weather.viewmodel.SettingsViewModel
-class SettingsFragment : PreferenceFragmentCompat() {
+class SettingsFragment : BasePreferencesFragment(R.xml.prefs) {
- override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
- setPreferencesFromResource(R.xml.prefs, rootKey)
+ override fun preferenceChanged(key: String) {
+ when (key) {
- //listener on changed sort order preference:
- val prefs = PreferenceManager.getDefaultSharedPreferences(requireContext())
- prefs.registerOnSharedPreferenceChangeListener { _, key ->
- if (key == "temp_units") {
- val intent = Intent(requireContext(), NewAppWidget::class.java)
- intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
- val ids = AppWidgetManager.getInstance(requireContext())
- .getAppWidgetIds(ComponentName(requireContext(), NewAppWidget::class.java))
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
- requireContext().sendBroadcast(intent)
- }
- if (key == "notif_boolean") {
- setupNotificationBroadcaster(requireContext())
- }
-
- if (key == "widget_black_background") {
- val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
- val widgetManager = AppWidgetManager.getInstance(requireContext())
- val ids =
- widgetManager.getAppWidgetIds(
- ComponentName(
- requireContext(),
- NewAppWidget::class.java
- )
- )
- AppWidgetManager.getInstance(requireContext())
- .notifyAppWidgetViewDataChanged(ids, R.id.whole_widget_view)
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
- requireContext().sendBroadcast(intent)
+ "temp_units" -> viewModel.refreshWeatherData()
+ "notif_boolean" -> {
+ // TODO: update notification
+// viewModel.updateWidget()
+// displayToast("Widget background has been updates")
}
}
}
- fun setupNotificationBroadcaster(context: Context) {
- val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
- val notificationIntent = Intent(context, NotificationReceiver::class.java)
- val broadcast = PendingIntent.getBroadcast(
- context, 100, notificationIntent,
- PendingIntent.FLAG_UPDATE_CURRENT
- )
- val cal: Calendar = Calendar.getInstance()
- cal.set(Calendar.HOUR_OF_DAY, 6)
- cal.set(Calendar.MINUTE, 8)
- cal.set(Calendar.SECOND, 5)
- alarmManager.setRepeating(
- AlarmManager.RTC_WAKEUP,
- cal.timeInMillis,
- AlarmManager.INTERVAL_DAY,
- broadcast
- )
+ override fun onSuccess(data: Any?) {
+ super.onSuccess(data)
+ if (data is String) displayToast(data)
}
-}
\ No newline at end of file
+}
+
+// override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+// setPreferencesFromResource(R.xml.prefs, rootKey)
+//
+// //listener on changed sort order preference:
+// val prefs = PreferenceManager.getDefaultSharedPreferences(requireContext())
+// prefs.registerOnSharedPreferenceChangeListener { _, key ->
+// if (key == "temp_units") {
+//
+// }
+// if (key == "notif_boolean") {
+// setupNotificationBroadcaster(requireContext())
+// }
+// }
+// }
+//
+// fun setupNotificationBroadcaster(context: Context) {
+// val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
+// val notificationIntent = Intent(context, NotificationReceiver::class.java)
+// val broadcast = PendingIntent.getBroadcast(
+// context, 100, notificationIntent,
+// PendingIntent.FLAG_UPDATE_CURRENT
+// )
+// val cal: Calendar = Calendar.getInstance()
+// cal.set(Calendar.HOUR_OF_DAY, 6)
+// cal.set(Calendar.MINUTE, 8)
+// cal.set(Calendar.SECOND, 5)
+// alarmManager.setRepeating(
+// AlarmManager.RTC_WAKEUP,
+// cal.timeInMillis,
+// AlarmManager.INTERVAL_DAY,
+// broadcast
+// )
+// }
+//}
\ No newline at end of file
diff --git a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/world/AddLocationFragment.kt b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/world/AddLocationFragment.kt
index e9d72df..9d45c22 100644
--- a/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/world/AddLocationFragment.kt
+++ b/app/src/atlasWeather/java/com/appttude/h_mal/atlas_weather/ui/world/AddLocationFragment.kt
@@ -2,13 +2,13 @@ package com.appttude.h_mal.atlas_weather.ui.world
import android.os.Bundle
import android.view.View
+import android.widget.Button
+import android.widget.TextView
import com.appttude.h_mal.atlas_weather.R
import com.appttude.h_mal.atlas_weather.base.BaseFragment
import com.appttude.h_mal.atlas_weather.utils.displayToast
import com.appttude.h_mal.atlas_weather.utils.goBack
import com.appttude.h_mal.atlas_weather.viewmodel.WorldViewModel
-import kotlinx.android.synthetic.main.activity_add_forecast.location_name_tv
-import kotlinx.android.synthetic.main.activity_add_forecast.submit
class AddLocationFragment : BaseFragment(R.layout.activity_add_forecast) {
@@ -16,8 +16,11 @@ class AddLocationFragment : BaseFragment(R.layout.activity_add_f
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
+ val submit = view.findViewById