Add permissions requests to wear OS sensors and add network sensors (#2956)

* Add permissions requests to wear OS sensors

* Add intents for network sensors on wear

* Separate background/foreground location permission requests

* Prompt for background permissions after foreground was successful

* Only set sensor to enabled if all permissions are grantted

* Review comments

* Process more review comments

* Remove unnecessary variable update
This commit is contained in:
Daniel Shokouhi 2022-10-19 11:48:35 -07:00 committed by GitHub
parent 4ded46af4d
commit 7c792c4d4b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 18 deletions

View file

@ -4,6 +4,8 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-feature android:name="android.hardware.type.watch" />

View file

@ -3,6 +3,7 @@ package io.homeassistant.companion.android
import android.app.Application
import android.content.Intent
import android.content.IntentFilter
import android.net.wifi.WifiManager
import dagger.hilt.android.HiltAndroidApp
import io.homeassistant.companion.android.complications.ComplicationReceiver
import io.homeassistant.companion.android.sensors.SensorReceiver
@ -26,6 +27,15 @@ open class HomeAssistantApplication : Application() {
}
)
// This will trigger an update any time the wifi state has changed
registerReceiver(
sensorReceiver,
IntentFilter().apply {
addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION)
addAction(WifiManager.WIFI_STATE_CHANGED_ACTION)
}
)
// Update complications when the screen is on
val complicationReceiver = ComplicationReceiver()

View file

@ -21,6 +21,7 @@ import io.homeassistant.companion.android.data.SimplifiedEntity
import io.homeassistant.companion.android.database.sensor.SensorDao
import io.homeassistant.companion.android.database.wear.FavoritesDao
import io.homeassistant.companion.android.database.wear.getAllFlow
import io.homeassistant.companion.android.sensors.SensorWorker
import io.homeassistant.companion.android.util.RegistriesDataHandler
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.Flow
@ -278,6 +279,7 @@ class MainViewModel @Inject constructor(
isEnabled: Boolean
) {
sensorDao.setSensorsEnabled(listOf(basicSensor.id), isEnabled)
SensorWorker.start(getApplication())
}
fun getAreaForEntity(entityId: String): AreaRegistryResponse? =

View file

@ -1,5 +1,9 @@
package io.homeassistant.companion.android.home.views
import android.Manifest
import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@ -21,13 +25,48 @@ fun SensorUi(
basicSensor: SensorManager.BasicSensor,
onSensorClicked: (String, Boolean) -> Unit,
) {
val perm = manager.checkPermission(LocalContext.current, basicSensor.id)
val checked = sensor?.enabled == true
val backgroundRequest =
rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) {
onSensorClicked(basicSensor.id, it)
}
val permissionLaunch = rememberLauncherForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { isGranted ->
var allGranted = true
isGranted.forEach {
if (
manager.requiredPermissions(basicSensor.id).contains(Manifest.permission.ACCESS_FINE_LOCATION) &&
manager.requiredPermissions(basicSensor.id).contains(Manifest.permission.ACCESS_BACKGROUND_LOCATION) &&
it.key == Manifest.permission.ACCESS_FINE_LOCATION && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
) {
backgroundRequest.launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
return@forEach
}
if (!it.value)
allGranted = false
}
onSensorClicked(basicSensor.id, allGranted)
}
val perm = manager.checkPermission(LocalContext.current, basicSensor.id)
ToggleChip(
checked = (sensor == null && manager.enabledByDefault) ||
(sensor?.enabled == true && perm),
onCheckedChange = { enabled ->
onSensorClicked(basicSensor.id, enabled)
val permissions = manager.requiredPermissions(basicSensor.id)
if (perm || !enabled)
onSensorClicked(basicSensor.id, enabled)
else
permissionLaunch.launch(
if (permissions.size == 1 && permissions[0] == Manifest.permission.ACCESS_BACKGROUND_LOCATION)
permissions
else
permissions.toSet().minus(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
.toTypedArray()
)
},
modifier = Modifier
.fillMaxWidth(),

View file

@ -44,20 +44,19 @@ fun SensorsView(
ListHeader(id = commonR.string.sensors)
}
items(sensorManagers.size, { sensorManagers[it].name }) { index ->
sensorManagers.forEach { manager ->
Row {
Chip(
modifier = Modifier
.fillMaxWidth(),
colors = ChipDefaults.secondaryChipColors(),
label = {
Text(
text = stringResource(manager.name)
)
},
onClick = { onClickSensorManager(manager) }
)
}
val manager = sensorManagers[index]
Row {
Chip(
modifier = Modifier
.fillMaxWidth(),
colors = ChipDefaults.secondaryChipColors(),
label = {
Text(
text = stringResource(manager.name)
)
},
onClick = { onClickSensorManager(manager) }
)
}
}
}

View file

@ -3,9 +3,11 @@ package io.homeassistant.companion.android.sensors
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.net.wifi.WifiManager
import dagger.hilt.android.AndroidEntryPoint
import io.homeassistant.companion.android.BuildConfig
import io.homeassistant.companion.android.common.sensors.BatterySensorManager
import io.homeassistant.companion.android.common.sensors.NetworkSensorManager
import io.homeassistant.companion.android.common.sensors.SensorManager
import io.homeassistant.companion.android.common.sensors.SensorReceiverBase
@ -24,7 +26,8 @@ class SensorReceiver : SensorReceiverBase() {
companion object {
const val TAG = "SensorReceiver"
val MANAGERS = listOf(
BatterySensorManager()
BatterySensorManager(),
NetworkSensorManager()
)
const val ACTION_REQUEST_SENSORS_UPDATE =
@ -33,7 +36,9 @@ class SensorReceiver : SensorReceiverBase() {
// Suppress Lint because we only register for the receiver if the android version matches the intent
@SuppressLint("InlinedApi")
override val skippableActions = mapOf<String, String>()
override val skippableActions = mapOf(
WifiManager.WIFI_STATE_CHANGED_ACTION to NetworkSensorManager.wifiState.id
)
override fun getSensorSettingsIntent(context: Context, id: String): Intent? = null
}