diff --git a/app/build.gradle b/app/build.gradle
index 435a2f567..713756583 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -166,7 +166,7 @@ ext {
}
dependencies {
- implementation "io.github.wulkanowy:sdk:230d2075df"
+ implementation "io.github.wulkanowy:sdk:49c2071d10"
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ad5adaf2e..77ce3506c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -93,6 +93,13 @@
+
+
+
+
+
?
@@ -230,8 +235,10 @@ class PreferencesRepository @Inject constructor(
set(value) = sharedPref.edit().putInt(PREF_KEY_IN_APP_REVIEW_COUNT, value).apply()
var inAppReviewDate: LocalDate?
- get() = sharedPref.getLong(PREF_KEY_IN_APP_REVIEW_DATE, 0).takeIf { it != 0L }?.toLocalDate()
- set(value) = sharedPref.edit().putLong(PREF_KEY_IN_APP_REVIEW_DATE, value!!.toTimestamp()).apply()
+ get() = sharedPref.getLong(PREF_KEY_IN_APP_REVIEW_DATE, 0).takeIf { it != 0L }
+ ?.toLocalDate()
+ set(value) = sharedPref.edit().putLong(PREF_KEY_IN_APP_REVIEW_DATE, value!!.toTimestamp())
+ .apply()
var isAppReviewDone: Boolean
get() = sharedPref.getBoolean(PREF_KEY_IN_APP_REVIEW_DONE, false)
diff --git a/app/src/main/java/io/github/wulkanowy/services/piggyback/VulcanNotificationListenerService.kt b/app/src/main/java/io/github/wulkanowy/services/piggyback/VulcanNotificationListenerService.kt
new file mode 100644
index 000000000..c7df2dbc1
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/services/piggyback/VulcanNotificationListenerService.kt
@@ -0,0 +1,24 @@
+package io.github.wulkanowy.services.piggyback
+
+import android.service.notification.NotificationListenerService
+import android.service.notification.StatusBarNotification
+import dagger.hilt.android.AndroidEntryPoint
+import io.github.wulkanowy.data.repositories.PreferencesRepository
+import io.github.wulkanowy.services.sync.SyncManager
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class VulcanNotificationListenerService : NotificationListenerService() {
+
+ @Inject
+ lateinit var syncManager: SyncManager
+
+ @Inject
+ lateinit var preferenceRepository: PreferencesRepository
+
+ override fun onNotificationPosted(statusBarNotification: StatusBarNotification?) {
+ if (statusBarNotification?.packageName == "pl.edu.vulcan.hebe" && preferenceRepository.isNotificationPiggybackEnabled) {
+ syncManager.startOneTimeSyncWorker()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt b/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt
index b94d97e33..02d8b964f 100644
--- a/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt
+++ b/app/src/main/java/io/github/wulkanowy/services/sync/SyncManager.kt
@@ -57,14 +57,20 @@ class SyncManager @Inject constructor(
fun startPeriodicSyncWorker(restart: Boolean = false) {
if (preferencesRepository.isServiceEnabled && !now().isHolidays) {
- workManager.enqueueUniquePeriodicWork(SyncWorker::class.java.simpleName, if (restart) REPLACE else KEEP,
- PeriodicWorkRequestBuilder(preferencesRepository.servicesInterval, MINUTES)
+ val serviceInterval = preferencesRepository.servicesInterval
+
+ workManager.enqueueUniquePeriodicWork(
+ SyncWorker::class.java.simpleName, if (restart) REPLACE else KEEP,
+ PeriodicWorkRequestBuilder(serviceInterval, MINUTES)
.setInitialDelay(10, MINUTES)
.setBackoffCriteria(EXPONENTIAL, 30, MINUTES)
- .setConstraints(Constraints.Builder()
- .setRequiredNetworkType(if (preferencesRepository.isServicesOnlyWifi) UNMETERED else CONNECTED)
- .build())
- .build())
+ .setConstraints(
+ Constraints.Builder()
+ .setRequiredNetworkType(if (preferencesRepository.isServicesOnlyWifi) UNMETERED else CONNECTED)
+ .build()
+ )
+ .build()
+ )
}
}
@@ -77,7 +83,11 @@ class SyncManager @Inject constructor(
)
.build()
- workManager.enqueueUniqueWork("${SyncWorker::class.java.simpleName}_one_time", ExistingWorkPolicy.REPLACE, work)
+ workManager.enqueueUniqueWork(
+ "${SyncWorker::class.java.simpleName}_one_time",
+ ExistingWorkPolicy.REPLACE,
+ work
+ )
return workManager.getWorkInfoByIdLiveData(work.id).asFlow()
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt
index 0fc7e68e7..207d587de 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsFragment.kt
@@ -10,9 +10,12 @@ import android.provider.Settings
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
+import androidx.core.app.NotificationManagerCompat
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
+import androidx.preference.SwitchPreferenceCompat
import androidx.recyclerview.widget.RecyclerView
import com.thelittlefireman.appkillermanager.AppKillerManager
import com.thelittlefireman.appkillermanager.exceptions.NoActionFoundException
@@ -43,6 +46,21 @@ class NotificationsFragment : PreferenceFragmentCompat(),
override val titleStringId get() = R.string.pref_settings_notifications_title
+ override val isNotificationPermissionGranted: Boolean
+ get() {
+ val packageNameList =
+ NotificationManagerCompat.getEnabledListenerPackages(requireContext())
+ val appPackageName = requireContext().packageName
+
+ return appPackageName in packageNameList
+ }
+
+ private val notificationSettingsContract =
+ registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
+
+ presenter.onNotificationPermissionResult()
+ }
+
override fun initView(showDebugNotificationSwitch: Boolean) {
findPreference(getString(R.string.pref_key_notification_debug))?.isVisible =
showDebugNotificationSwitch
@@ -57,12 +75,11 @@ class NotificationsFragment : PreferenceFragmentCompat(),
}
}
- findPreference(getString(R.string.pref_key_notifications_system_settings))?.run {
- setOnPreferenceClickListener {
+ findPreference(getString(R.string.pref_key_notifications_system_settings))
+ ?.setOnPreferenceClickListener {
presenter.onOpenSystemSettingsClicked()
true
}
- }
}
override fun onCreateRecyclerView(
@@ -157,6 +174,24 @@ class NotificationsFragment : PreferenceFragmentCompat(),
}
}
+ override fun openNotificationPermissionDialog() {
+ AlertDialog.Builder(requireContext())
+ .setTitle(getString(R.string.pref_notification_piggyback_popup_title))
+ .setMessage(getString(R.string.pref_notification_piggyback_popup_description))
+ .setPositiveButton(getString(R.string.pref_notification_piggyback_popup_positive)) { _, _ ->
+ notificationSettingsContract.launch(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
+ }
+ .setNegativeButton(android.R.string.cancel) { _, _ ->
+ setNotificationPiggybackPreferenceChecked(false)
+ }
+ .show()
+ }
+
+ override fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean) {
+ findPreference(getString(R.string.pref_key_notifications_piggyback))?.isChecked =
+ isChecked
+ }
+
override fun onResume() {
super.onResume()
preferenceScreen.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt
index 8366d3094..19d2f5591 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsPresenter.kt
@@ -31,6 +31,9 @@ class NotificationsPresenter @Inject constructor(
)
initView(appInfo.isDebug)
}
+
+ checkNotificationPiggybackState()
+
Timber.i("Settings notifications view was initialized")
}
@@ -47,6 +50,11 @@ class NotificationsPresenter @Inject constructor(
isDebugNotificationEnableKey -> {
chuckerCollector.showNotification = isDebugNotificationEnable
}
+ isNotificationPiggybackEnabledKey -> {
+ if (isNotificationPiggybackEnabled && view?.isNotificationPermissionGranted == false) {
+ view?.openNotificationPermissionDialog()
+ }
+ }
}
}
analytics.logEvent("setting_changed", "name" to key)
@@ -59,4 +67,18 @@ class NotificationsPresenter @Inject constructor(
fun onOpenSystemSettingsClicked() {
view?.openSystemSettings()
}
+
+ fun onNotificationPermissionResult() {
+ view?.run {
+ setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted)
+ }
+ }
+
+ private fun checkNotificationPiggybackState() {
+ if (preferencesRepository.isNotificationPiggybackEnabled) {
+ view?.run {
+ setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted)
+ }
+ }
+ }
}
diff --git a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt
index 2ab9b0352..42862b380 100644
--- a/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt
+++ b/app/src/main/java/io/github/wulkanowy/ui/modules/settings/notifications/NotificationsView.kt
@@ -4,6 +4,8 @@ import io.github.wulkanowy.ui.base.BaseView
interface NotificationsView : BaseView {
+ val isNotificationPermissionGranted: Boolean
+
fun initView(showDebugNotificationSwitch: Boolean)
fun showFixSyncDialog()
@@ -11,4 +13,8 @@ interface NotificationsView : BaseView {
fun openSystemSettings()
fun enableNotification(notificationKey: String, enable: Boolean)
+
+ fun openNotificationPermissionDialog()
+
+ fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean)
}
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 6ac94a4ed..d1f44e5c2 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -624,6 +624,10 @@
Przejdź do ustawień
Pokazuj powiadomienia debugowania
Synchronizacja jest wyłączona
+ Przechwytywanie powiadomień oficjalnej aplikacji
+ Przechwytywanie powiadomień
+ Dzięki tej funkcji możesz zyskać namiastkę powiadomień push takich, jak w oficjalnej aplikacji. Wystarczy że zezwolisz Wulkanowemu na odbieranie wszystkich powiadomień w ustawieniach systemowych.\n\nJak to działa?\nGdy dostaniesz powiadomienie w Dzienniczku VULCANa Wulkanowy zostanie o tym powiadomiony (po to te dodatkowe uprawnienia) i uruchomi synchronizację, dzięki czemu będzie mógł wysłać własne powiadomienie.\n\nTYLKO DLA ZAAWANSOWANYCH UŻYTKOWNIKÓW
+ Przejdź do ustawień
Synchronizacja
Automatyczna aktualizacja
Zawieszona na wakacjach
diff --git a/app/src/main/res/values/preferences_defaults.xml b/app/src/main/res/values/preferences_defaults.xml
index 1ba9359cd..9286052d8 100644
--- a/app/src/main/res/values/preferences_defaults.xml
+++ b/app/src/main/res/values/preferences_defaults.xml
@@ -26,6 +26,7 @@
false
false
0
+ false
- LUCKY_NUMBER
- MESSAGES
diff --git a/app/src/main/res/values/preferences_keys.xml b/app/src/main/res/values/preferences_keys.xml
index 09dac7002..bae6a617b 100644
--- a/app/src/main/res/values/preferences_keys.xml
+++ b/app/src/main/res/values/preferences_keys.xml
@@ -32,4 +32,5 @@
message_send_is_draft
message_send_recipients
last_sync_date
+ notifications_piggyback
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 575401100..af2006037 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -625,6 +625,10 @@
Go to settings
Show debug notifications
Synchronization is disabled
+ Capture official app notifications
+ Capture notifications
+ With this feature you can gain a substitute of push notifications like in the official app. All you need to do is allow Wulkanowy to receive all notifications in your system settings.\n\nHow it works?\nWhen you get a notification in Dziennik VULCAN, Wulkanowy will be notified (that\'s what these extra permissions are for) and will trigger a sync so that can send its own notification.\n\nFOR ADVANCED USERS ONLY
+ Go to settings
Synchronization
Automatic update
diff --git a/app/src/main/res/xml/scheme_preferences_notifications.xml b/app/src/main/res/xml/scheme_preferences_notifications.xml
index ac88746c0..24b83169b 100644
--- a/app/src/main/res/xml/scheme_preferences_notifications.xml
+++ b/app/src/main/res/xml/scheme_preferences_notifications.xml
@@ -14,6 +14,12 @@
app:key="@string/pref_key_notifications_upcoming_lessons_enable"
app:singleLineTitle="false"
app:title="@string/pref_notify_upcoming_lessons_switch" />
+