Skip to content

Commit

Permalink
Handle notification permission on Wear (#4551)
Browse files Browse the repository at this point in the history
- Ask for notification permission after completing onboarding
 - Add a settings item to open the watch notification settings to grant permission
  • Loading branch information
jpelgrom authored Sep 6, 2024
1 parent 445939f commit 7a9efaa
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package io.homeassistant.companion.android.home

import android.Manifest
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.core.app.NotificationManagerCompat
import androidx.core.net.toUri
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
Expand All @@ -32,11 +36,18 @@ class HomeActivity : ComponentActivity(), HomeView {

private var entityUpdateJob: Job? = null

private val permissionRequest = registerForActivityResult(ActivityResultContracts.RequestPermission()) {
mainViewModel.refreshNotificationPermission()
}

companion object {
private const val TAG = "HomeActivity"
private const val EXTRA_FROM_ONBOARDING = "from_onboarding"

fun newInstance(context: Context): Intent {
return Intent(context, HomeActivity::class.java)
fun newInstance(context: Context, fromOnboarding: Boolean = false): Intent {
return Intent(context, HomeActivity::class.java).apply {
putExtra(EXTRA_FROM_ONBOARDING, fromOnboarding)
}
}

fun getCameraTileSettingsIntent(
Expand Down Expand Up @@ -110,6 +121,14 @@ class HomeActivity : ComponentActivity(), HomeView {
mainViewModel.updateUI()
}
}
if (
intent.getBooleanExtra(EXTRA_FROM_ONBOARDING, false) &&
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
!NotificationManagerCompat.from(this@HomeActivity).areNotificationsEnabled()
) {
permissionRequest.launch(Manifest.permission.POST_NOTIFICATIONS)
intent.removeExtra(EXTRA_FROM_ONBOARDING)
}
}

override fun onPause() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.runtime.toMutableStateList
import androidx.core.app.NotificationManagerCompat
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
Expand Down Expand Up @@ -130,6 +131,8 @@ class MainViewModel @Inject constructor(
private set
var isAssistantAppAllowed by mutableStateOf(true)
private set
var areNotificationsAllowed by mutableStateOf(false)
private set

fun supportedDomains(): List<String> = HomePresenterImpl.supportedDomains

Expand Down Expand Up @@ -159,6 +162,8 @@ class MainViewModel @Inject constructor(
)
isAssistantAppAllowed =
app.packageManager.getComponentEnabledSetting(assistantAppComponent) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED

refreshNotificationPermission()
}
}

Expand Down Expand Up @@ -546,6 +551,10 @@ class MainViewModel @Inject constructor(
isAssistantAppAllowed = allowed
}

fun refreshNotificationPermission() {
areNotificationsAllowed = NotificationManagerCompat.from(app).areNotificationsEnabled()
}

fun logout() {
homePresenter.onLogoutClicked()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package io.homeassistant.companion.android.home.views

import android.content.Intent
import android.provider.Settings
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
Expand Down Expand Up @@ -134,6 +138,9 @@ fun LoadHomePage(
)
}
composable(SCREEN_SETTINGS) {
val notificationLaunch = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
mainViewModel.refreshNotificationPermission()
}
SettingsView(
loadingState = mainViewModel.loadingState.value,
favorites = mainViewModel.favoriteEntityIds.value,
Expand All @@ -159,6 +166,7 @@ fun LoadHomePage(
isToastEnabled = mainViewModel.isToastEnabled.value,
isFavoritesOnly = mainViewModel.isFavoritesOnly,
isAssistantAppAllowed = mainViewModel.isAssistantAppAllowed,
areNotificationsAllowed = mainViewModel.areNotificationsAllowed,
onHapticEnabled = { mainViewModel.setHapticEnabled(it) },
onToastEnabled = { mainViewModel.setToastEnabled(it) },
setFavoritesOnly = { mainViewModel.setWearFavoritesOnly(it) },
Expand All @@ -169,7 +177,14 @@ fun LoadHomePage(
mainViewModel.loadTemplateTiles()
swipeDismissableNavController.navigate("$ROUTE_TEMPLATE_TILE/$SCREEN_SELECT_TEMPLATE_TILE")
},
onAssistantAppAllowed = mainViewModel::setAssistantApp
onAssistantAppAllowed = mainViewModel::setAssistantApp,
onClickNotifications = {
notificationLaunch.launch(
Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
}
)
}
)
}
composable(SCREEN_SET_FAVORITES) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,14 @@ fun SettingsView(
isToastEnabled: Boolean,
isFavoritesOnly: Boolean,
isAssistantAppAllowed: Boolean,
areNotificationsAllowed: Boolean,
onHapticEnabled: (Boolean) -> Unit,
onToastEnabled: (Boolean) -> Unit,
setFavoritesOnly: (Boolean) -> Unit,
onClickCameraTile: () -> Unit,
onClickTemplateTiles: () -> Unit,
onAssistantAppAllowed: (Boolean) -> Unit
onAssistantAppAllowed: (Boolean) -> Unit,
onClickNotifications: () -> Unit
) {
WearAppTheme {
ThemeLazyColumn {
Expand Down Expand Up @@ -224,6 +226,20 @@ fun SettingsView(
colors = getToggleButtonColors()
)
}
if (!areNotificationsAllowed) {
item {
ListHeader(
id = commonR.string.notifications
)
}
item {
SecondarySettingsChip(
icon = CommunityMaterial.Icon.cmd_bell_ring,
label = stringResource(commonR.string.suggestion_notifications_title),
onClick = onClickNotifications
)
}
}
item {
ListHeader(
id = commonR.string.account
Expand Down Expand Up @@ -268,11 +284,13 @@ private fun PreviewSettingsView() {
isToastEnabled = false,
isFavoritesOnly = false,
isAssistantAppAllowed = true,
areNotificationsAllowed = false,
onHapticEnabled = {},
onToastEnabled = {},
setFavoritesOnly = {},
onClickCameraTile = {},
onClickTemplateTiles = {},
onAssistantAppAllowed = {}
onAssistantAppAllowed = {},
onClickNotifications = {}
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class MobileAppIntegrationActivity : AppCompatActivity(), MobileAppIntegrationVi
}

override fun deviceRegistered() {
val intent = HomeActivity.newInstance(this)
val intent = HomeActivity.newInstance(this, fromOnboarding = true)
// empty the back stack
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ class PhoneSettingsListener : WearableListenerService(), DataClient.OnDataChange
updateTiles()
}

val intent = HomeActivity.newInstance(applicationContext)
val intent = HomeActivity.newInstance(applicationContext, fromOnboarding = true)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
} catch (e: Exception) {
Expand Down

0 comments on commit 7a9efaa

Please sign in to comment.