mirror of
https://github.com/home-assistant/android
synced 2024-09-19 08:01:31 +00:00
Add notification history page to settings (#1054)
* Add notification history page to settings * Attempt to fix lint minimal errors * Attempt to fix minimal errors again * Remove minimal files to revert back to original commit * Remove unneeded stuff
This commit is contained in:
parent
1f48c44f44
commit
e0f2eab639
|
@ -35,6 +35,8 @@ import io.homeassistant.companion.android.common.data.authentication.SessionStat
|
||||||
import io.homeassistant.companion.android.common.data.integration.DeviceRegistration
|
import io.homeassistant.companion.android.common.data.integration.DeviceRegistration
|
||||||
import io.homeassistant.companion.android.common.data.integration.IntegrationRepository
|
import io.homeassistant.companion.android.common.data.integration.IntegrationRepository
|
||||||
import io.homeassistant.companion.android.common.data.url.UrlRepository
|
import io.homeassistant.companion.android.common.data.url.UrlRepository
|
||||||
|
import io.homeassistant.companion.android.database.AppDatabase
|
||||||
|
import io.homeassistant.companion.android.database.notification.NotificationItem
|
||||||
import io.homeassistant.companion.android.sensors.LocationSensorManager
|
import io.homeassistant.companion.android.sensors.LocationSensorManager
|
||||||
import io.homeassistant.companion.android.util.UrlHandler
|
import io.homeassistant.companion.android.util.UrlHandler
|
||||||
import io.homeassistant.companion.android.util.cancel
|
import io.homeassistant.companion.android.util.cancel
|
||||||
|
@ -114,6 +116,10 @@ class MessagingService : FirebaseMessagingService() {
|
||||||
// Check if message contains a data payload.
|
// Check if message contains a data payload.
|
||||||
remoteMessage.data.let {
|
remoteMessage.data.let {
|
||||||
Log.d(TAG, "Message data payload: " + remoteMessage.data)
|
Log.d(TAG, "Message data payload: " + remoteMessage.data)
|
||||||
|
val notificationDao = AppDatabase.getInstance(applicationContext).notificationDao()
|
||||||
|
val now = System.currentTimeMillis()
|
||||||
|
val notificationRow = NotificationItem(0, now, it[MESSAGE].toString(), it.toString())
|
||||||
|
notificationDao.add(notificationRow)
|
||||||
|
|
||||||
when {
|
when {
|
||||||
it[MESSAGE] == REQUEST_LOCATION_UPDATE -> {
|
it[MESSAGE] == REQUEST_LOCATION_UPDATE -> {
|
||||||
|
|
|
@ -19,6 +19,8 @@ import io.homeassistant.companion.android.R
|
||||||
import io.homeassistant.companion.android.common.data.integration.IntegrationRepository
|
import io.homeassistant.companion.android.common.data.integration.IntegrationRepository
|
||||||
import io.homeassistant.companion.android.database.authentication.Authentication
|
import io.homeassistant.companion.android.database.authentication.Authentication
|
||||||
import io.homeassistant.companion.android.database.authentication.AuthenticationDao
|
import io.homeassistant.companion.android.database.authentication.AuthenticationDao
|
||||||
|
import io.homeassistant.companion.android.database.notification.NotificationDao
|
||||||
|
import io.homeassistant.companion.android.database.notification.NotificationItem
|
||||||
import io.homeassistant.companion.android.database.sensor.Attribute
|
import io.homeassistant.companion.android.database.sensor.Attribute
|
||||||
import io.homeassistant.companion.android.database.sensor.Sensor
|
import io.homeassistant.companion.android.database.sensor.Sensor
|
||||||
import io.homeassistant.companion.android.database.sensor.SensorDao
|
import io.homeassistant.companion.android.database.sensor.SensorDao
|
||||||
|
@ -42,9 +44,10 @@ import kotlinx.coroutines.runBlocking
|
||||||
ButtonWidgetEntity::class,
|
ButtonWidgetEntity::class,
|
||||||
MediaPlayerControlsWidgetEntity::class,
|
MediaPlayerControlsWidgetEntity::class,
|
||||||
StaticWidgetEntity::class,
|
StaticWidgetEntity::class,
|
||||||
TemplateWidgetEntity::class
|
TemplateWidgetEntity::class,
|
||||||
|
NotificationItem::class
|
||||||
],
|
],
|
||||||
version = 12,
|
version = 13,
|
||||||
exportSchema = false
|
exportSchema = false
|
||||||
)
|
)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
@ -54,6 +57,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
abstract fun mediaPlayCtrlWidgetDao(): MediaPlayerControlsWidgetDao
|
abstract fun mediaPlayCtrlWidgetDao(): MediaPlayerControlsWidgetDao
|
||||||
abstract fun staticWidgetDao(): StaticWidgetDao
|
abstract fun staticWidgetDao(): StaticWidgetDao
|
||||||
abstract fun templateWidgetDao(): TemplateWidgetDao
|
abstract fun templateWidgetDao(): TemplateWidgetDao
|
||||||
|
abstract fun notificationDao(): NotificationDao
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val DATABASE_NAME = "HomeAssistantDB"
|
private const val DATABASE_NAME = "HomeAssistantDB"
|
||||||
|
@ -89,7 +93,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
MIGRATION_8_9,
|
MIGRATION_8_9,
|
||||||
MIGRATION_9_10,
|
MIGRATION_9_10,
|
||||||
MIGRATION_10_11,
|
MIGRATION_10_11,
|
||||||
MIGRATION_11_12
|
MIGRATION_11_12,
|
||||||
|
MIGRATION_12_13
|
||||||
)
|
)
|
||||||
.fallbackToDestructiveMigration()
|
.fallbackToDestructiveMigration()
|
||||||
.build()
|
.build()
|
||||||
|
@ -266,6 +271,12 @@ abstract class AppDatabase : RoomDatabase() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val MIGRATION_12_13 = object : Migration(12, 13) {
|
||||||
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
|
database.execSQL("CREATE TABLE IF NOT EXISTS `notification_history` (`id` INTEGER NOT NULL, `received` LONG NOT NULL, `message` TEXT NOT NULL, `data` TEXT NOT NULL, PRIMARY KEY(`id`))")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createNotificationChannel() {
|
private fun createNotificationChannel() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
val notificationManager = appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
val notificationManager = appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package io.homeassistant.companion.android.database.notification
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface NotificationDao {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM notification_history WHERE id = :id")
|
||||||
|
fun get(id: Int): NotificationItem?
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
fun add(notification: NotificationItem)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM notification_history ORDER BY received DESC")
|
||||||
|
fun getAll(): Array<NotificationItem>?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM notification_history ORDER BY received DESC LIMIT 25")
|
||||||
|
fun getLast25(): Array<NotificationItem>?
|
||||||
|
|
||||||
|
@Query("DELETE FROM notification_history WHERE id = :id")
|
||||||
|
fun delete(id: Int)
|
||||||
|
|
||||||
|
@Query("DELETE FROM notification_history")
|
||||||
|
fun deleteAll()
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package io.homeassistant.companion.android.database.notification
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity(tableName = "notification_history")
|
||||||
|
data class NotificationItem(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
val id: Int,
|
||||||
|
@ColumnInfo(name = "received")
|
||||||
|
val received: Long,
|
||||||
|
@ColumnInfo(name = "message")
|
||||||
|
val message: String,
|
||||||
|
@ColumnInfo(name = "data")
|
||||||
|
val data: String
|
||||||
|
)
|
|
@ -14,6 +14,7 @@ import androidx.biometric.BiometricManager
|
||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceCategory
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.SwitchPreference
|
import androidx.preference.SwitchPreference
|
||||||
import io.homeassistant.companion.android.BuildConfig
|
import io.homeassistant.companion.android.BuildConfig
|
||||||
|
@ -24,6 +25,7 @@ import io.homeassistant.companion.android.authenticator.Authenticator
|
||||||
import io.homeassistant.companion.android.common.dagger.GraphComponentAccessor
|
import io.homeassistant.companion.android.common.dagger.GraphComponentAccessor
|
||||||
import io.homeassistant.companion.android.nfc.NfcSetupActivity
|
import io.homeassistant.companion.android.nfc.NfcSetupActivity
|
||||||
import io.homeassistant.companion.android.sensors.SensorsSettingsFragment
|
import io.homeassistant.companion.android.sensors.SensorsSettingsFragment
|
||||||
|
import io.homeassistant.companion.android.settings.notification.NotificationHistoryFragment
|
||||||
import io.homeassistant.companion.android.settings.ssid.SsidDialogFragment
|
import io.homeassistant.companion.android.settings.ssid.SsidDialogFragment
|
||||||
import io.homeassistant.companion.android.settings.ssid.SsidPreference
|
import io.homeassistant.companion.android.settings.ssid.SsidPreference
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -128,6 +130,21 @@ class SettingsFragment : PreferenceFragmentCompat(), SettingsView {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BuildConfig.FLAVOR == "full") {
|
if (BuildConfig.FLAVOR == "full") {
|
||||||
|
findPreference<PreferenceCategory>("notifications")?.let {
|
||||||
|
it.isVisible = true
|
||||||
|
}
|
||||||
|
findPreference<Preference>("notification_history")?.let {
|
||||||
|
it.isVisible = true
|
||||||
|
it.setOnPreferenceClickListener {
|
||||||
|
parentFragmentManager
|
||||||
|
.beginTransaction()
|
||||||
|
.replace(R.id.content, NotificationHistoryFragment.newInstance())
|
||||||
|
.addToBackStack(getString(R.string.notifications))
|
||||||
|
.commit()
|
||||||
|
return@setOnPreferenceClickListener true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
findPreference<Preference>("notification_rate_limit")?.let {
|
findPreference<Preference>("notification_rate_limit")?.let {
|
||||||
val rateLimits = presenter.getNotificationRateLimits()
|
val rateLimits = presenter.getNotificationRateLimits()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package io.homeassistant.companion.android.settings.notification
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import io.homeassistant.companion.android.R
|
||||||
|
import io.homeassistant.companion.android.database.notification.NotificationItem
|
||||||
|
import java.util.Calendar
|
||||||
|
import java.util.GregorianCalendar
|
||||||
|
|
||||||
|
class NotificationDetailFragment(
|
||||||
|
private val notification: NotificationItem
|
||||||
|
) :
|
||||||
|
PreferenceFragmentCompat() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance(
|
||||||
|
notification: NotificationItem
|
||||||
|
): NotificationDetailFragment {
|
||||||
|
return NotificationDetailFragment(notification)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
|
||||||
|
addPreferencesFromResource(R.xml.notification_detail)
|
||||||
|
findPreference<Preference>("received_at")?.let {
|
||||||
|
val cal: Calendar = GregorianCalendar()
|
||||||
|
cal.timeInMillis = notification.received
|
||||||
|
it.summary = cal.time.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>("message")?.let {
|
||||||
|
it.summary = notification.message
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>("data")?.let {
|
||||||
|
it.summary = notification.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package io.homeassistant.companion.android.settings.notification
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceCategory
|
||||||
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import io.homeassistant.companion.android.R
|
||||||
|
import io.homeassistant.companion.android.database.AppDatabase
|
||||||
|
import java.util.Calendar
|
||||||
|
import java.util.GregorianCalendar
|
||||||
|
|
||||||
|
class NotificationHistoryFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance(): NotificationHistoryFragment {
|
||||||
|
return NotificationHistoryFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
|
||||||
|
setPreferencesFromResource(R.xml.notifications, rootKey)
|
||||||
|
val notificationDao = AppDatabase.getInstance(requireContext()).notificationDao()
|
||||||
|
val notificationList = notificationDao.getLast25()
|
||||||
|
|
||||||
|
val prefCategory = PreferenceCategory(preferenceScreen.context)
|
||||||
|
if (!notificationList.isNullOrEmpty()) {
|
||||||
|
prefCategory.title = requireContext().getString(R.string.last_25_notifications)
|
||||||
|
prefCategory.isIconSpaceReserved = false
|
||||||
|
preferenceScreen.addPreference(prefCategory)
|
||||||
|
for (item in notificationList) {
|
||||||
|
val pref = Preference(preferenceScreen.context)
|
||||||
|
val cal: Calendar = GregorianCalendar()
|
||||||
|
cal.timeInMillis = item.received
|
||||||
|
pref.key = item.id.toString()
|
||||||
|
pref.title = cal.time.toString()
|
||||||
|
pref.summary = item.message
|
||||||
|
pref.isIconSpaceReserved = false
|
||||||
|
|
||||||
|
pref.setOnPreferenceClickListener {
|
||||||
|
parentFragmentManager
|
||||||
|
.beginTransaction()
|
||||||
|
.replace(
|
||||||
|
R.id.content,
|
||||||
|
NotificationDetailFragment.newInstance(
|
||||||
|
item
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.addToBackStack("Notification Detail")
|
||||||
|
.commit()
|
||||||
|
return@setOnPreferenceClickListener true
|
||||||
|
}
|
||||||
|
|
||||||
|
prefCategory.addPreference(pref)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
findPreference<Preference>("no_notifications")?.let {
|
||||||
|
it.isVisible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
app/src/main/res/drawable/ic_notification_history.xml
Normal file
9
app/src/main/res/drawable/ic_notification_history.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="@color/colorAccent"
|
||||||
|
android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z"/>
|
||||||
|
</vector>
|
|
@ -162,8 +162,17 @@ Home Assistant instance</string>
|
||||||
<string name="nfc_write_tag_success">Successfully wrote nfc tag</string>
|
<string name="nfc_write_tag_success">Successfully wrote nfc tag</string>
|
||||||
<string name="nfc_write_tag_too_early">Please fill out the form first</string>
|
<string name="nfc_write_tag_too_early">Please fill out the form first</string>
|
||||||
<string name="not_private">Your connection to this site is not private.</string>
|
<string name="not_private">Your connection to this site is not private.</string>
|
||||||
|
<string name="notifications">Notifications</string>
|
||||||
<string name="notification_clear_failure">Failed to send event on notification cleared</string>
|
<string name="notification_clear_failure">Failed to send event on notification cleared</string>
|
||||||
<string name="notification_dismiss_failure">Failed to send event on notification dismissed</string>
|
<string name="notification_dismiss_failure">Failed to send event on notification dismissed</string>
|
||||||
|
<string name="notification_data">Full Notification Data</string>
|
||||||
|
<string name="notification_history">Notification History</string>
|
||||||
|
<string name="notification_history_summary">History of Notifications (currently displays the last 25 notifications received)</string>
|
||||||
|
<string name="notification_message">Message</string>
|
||||||
|
<string name="notification_received_at">Notification Received At</string>
|
||||||
|
<string name="last_25_notifications">Last 25 Notifications</string>
|
||||||
|
<string name="no_notifications">No Notifications</string>
|
||||||
|
<string name="no_notifications_summary">You have not received any notifications yet</string>
|
||||||
<string name="other_settings">Other Settings</string>
|
<string name="other_settings">Other Settings</string>
|
||||||
<string name="password">Password</string>
|
<string name="password">Password</string>
|
||||||
<string name="permission_explanation">In order to use location tracking features or different connection urls based on WiFi SSID we need access to your location. If you want consistent background updates you will also need to allow background processing</string>
|
<string name="permission_explanation">In order to use location tracking features or different connection urls based on WiFi SSID we need access to your location. If you want consistent background updates you will also need to allow background processing</string>
|
||||||
|
|
23
app/src/main/res/xml/notification_detail.xml
Normal file
23
app/src/main/res/xml/notification_detail.xml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.preference.PreferenceScreen
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
app:iconSpaceReserved="false">
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
app:key="received_at"
|
||||||
|
app:title="@string/notification_received_at"
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
app:enableCopying="true"/>
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
app:key="message"
|
||||||
|
app:title="@string/notification_message"
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
app:enableCopying="true" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
app:key="data"
|
||||||
|
app:title="@string/notification_data"
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
app:enableCopying="true" />
|
||||||
|
</androidx.preference.PreferenceScreen>
|
11
app/src/main/res/xml/notifications.xml
Normal file
11
app/src/main/res/xml/notifications.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.preference.PreferenceScreen
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<Preference
|
||||||
|
android:key="no_notifications"
|
||||||
|
android:title="@string/no_notifications"
|
||||||
|
android:summary="@string/no_notifications_summary"
|
||||||
|
android:selectable="false"
|
||||||
|
app:isPreferenceVisible="false" />
|
||||||
|
</androidx.preference.PreferenceScreen>
|
|
@ -86,7 +86,15 @@
|
||||||
</Preference>
|
</Preference>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:title="@string/app_version_info">
|
android:title="@string/notifications"
|
||||||
|
android:key="notifications"
|
||||||
|
app:isPreferenceVisible="false">
|
||||||
|
<Preference
|
||||||
|
android:key="notification_history"
|
||||||
|
app:isPreferenceVisible="false"
|
||||||
|
android:title="@string/notification_history"
|
||||||
|
android:icon="@drawable/ic_notification_history"
|
||||||
|
android:summary="@string/notification_history_summary" />
|
||||||
<Preference
|
<Preference
|
||||||
android:key="notification_rate_limit"
|
android:key="notification_rate_limit"
|
||||||
android:title="@string/rate_limit_title"
|
android:title="@string/rate_limit_title"
|
||||||
|
@ -94,6 +102,9 @@
|
||||||
app:enableCopying="true"
|
app:enableCopying="true"
|
||||||
android:icon="@drawable/ic_notifications"
|
android:icon="@drawable/ic_notifications"
|
||||||
android:summary="@string/rate_limit_summary"/>
|
android:summary="@string/rate_limit_summary"/>
|
||||||
|
</PreferenceCategory>
|
||||||
|
<PreferenceCategory
|
||||||
|
android:title="@string/app_version_info">
|
||||||
<Preference
|
<Preference
|
||||||
android:key="changelog"
|
android:key="changelog"
|
||||||
android:icon="@drawable/ic_changelog"
|
android:icon="@drawable/ic_changelog"
|
||||||
|
|
Loading…
Reference in a new issue