mirror of
https://github.com/home-assistant/android
synced 2024-10-15 12:32:54 +00:00
Added ChargingBroadcastReceiver which can instantly update plugged in… (#525)
* Added ChargingBroadcastReceiver which can instantly update plugged in status * Couple formatting changes noticed after pushing. Will squash this message * Addressed PR Comments * More PR comments! * Pulled out logic into SensorUpdater * Couple thigns I noticed after pushing... because of course I did. * Removed unnecessary Binds
This commit is contained in:
parent
4a9c6f0283
commit
825dd78f1e
|
@ -46,6 +46,13 @@
|
|||
android:resource="@xml/button_widget_info" />
|
||||
</receiver>
|
||||
|
||||
<!-- Start things like SensorWorker on device boot -->
|
||||
<receiver android:name=".HomeAssistantBootReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<activity android:name=".widgets.ButtonWidgetConfigureActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package io.homeassistant.companion.android
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import com.jakewharton.threetenabp.AndroidThreeTen
|
||||
import com.lokalise.sdk.Lokalise
|
||||
import io.homeassistant.companion.android.common.dagger.AppComponent
|
||||
import io.homeassistant.companion.android.common.dagger.Graph
|
||||
import io.homeassistant.companion.android.common.dagger.GraphComponentAccessor
|
||||
import io.homeassistant.companion.android.sensors.ChargingBroadcastReceiver
|
||||
import io.homeassistant.companion.android.sensors.SensorWorker
|
||||
|
||||
class HomeAssistantApplication : Application(), GraphComponentAccessor {
|
||||
|
||||
|
@ -19,6 +23,18 @@ class HomeAssistantApplication : Application(), GraphComponentAccessor {
|
|||
|
||||
AndroidThreeTen.init(this)
|
||||
graph = Graph(this, 0)
|
||||
// Start the sensor worker if they start the app. The only other place we start this ia Boot BroadcastReceiver
|
||||
SensorWorker.start(this)
|
||||
|
||||
// This will cause the sensor to be updated every time the OS broadcasts that a cable was plugged/unplugged.
|
||||
// This should be nearly instantaneous allowing automations to fire immediately when a phone is plugged
|
||||
// in or unplugged.
|
||||
registerReceiver(
|
||||
ChargingBroadcastReceiver(appComponent.integrationUseCase()), IntentFilter().apply {
|
||||
addAction(Intent.ACTION_POWER_CONNECTED)
|
||||
addAction(Intent.ACTION_POWER_DISCONNECTED)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override val appComponent: AppComponent
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package io.homeassistant.companion.android
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import io.homeassistant.companion.android.sensors.SensorWorker
|
||||
import io.homeassistant.companion.android.util.PermissionManager
|
||||
|
||||
/**
|
||||
* This class will receive a broadcast intent when the device boots up. This allows us to start the sensor worker
|
||||
* even if the user never starts the HomeAssistant app.
|
||||
*/
|
||||
class HomeAssistantBootReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
|
||||
SensorWorker.start(context)
|
||||
PermissionManager.restartLocationTracking(context)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package io.homeassistant.companion.android
|
||||
|
||||
interface SensorUpdater {
|
||||
suspend fun updateSensors()
|
||||
}
|
|
@ -19,7 +19,6 @@ import com.google.android.gms.location.LocationServices
|
|||
import io.homeassistant.companion.android.common.dagger.GraphComponentAccessor
|
||||
import io.homeassistant.companion.android.domain.integration.IntegrationUseCase
|
||||
import io.homeassistant.companion.android.domain.integration.UpdateLocation
|
||||
import io.homeassistant.companion.android.sensors.SensorWorker
|
||||
import io.homeassistant.companion.android.util.PermissionManager
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
@ -162,10 +161,6 @@ class LocationBroadcastReceiver : BroadcastReceiver() {
|
|||
}
|
||||
|
||||
private fun sendLocationUpdate(location: Location, context: Context) {
|
||||
// Anytime we send a location we should start the sensor worker.
|
||||
// This is cause it to send sensors then restart the 15 minute interval.
|
||||
SensorWorker.start(context)
|
||||
|
||||
Log.d(
|
||||
TAG, "Last Location: " +
|
||||
"\nCoords:(${location.latitude}, ${location.longitude})" +
|
||||
|
|
|
@ -16,7 +16,6 @@ import io.homeassistant.companion.android.onboarding.integration.MobileAppIntegr
|
|||
import io.homeassistant.companion.android.onboarding.integration.MobileAppIntegrationListener
|
||||
import io.homeassistant.companion.android.onboarding.manual.ManualSetupFragment
|
||||
import io.homeassistant.companion.android.onboarding.manual.ManualSetupListener
|
||||
import io.homeassistant.companion.android.sensors.SensorWorker
|
||||
import io.homeassistant.companion.android.webview.WebViewActivity
|
||||
|
||||
class OnboardingActivity : AppCompatActivity(), DiscoveryListener, ManualSetupListener,
|
||||
|
@ -90,7 +89,6 @@ class OnboardingActivity : AppCompatActivity(), DiscoveryListener, ManualSetupLi
|
|||
}
|
||||
|
||||
override fun onIntegrationRegistrationComplete() {
|
||||
SensorWorker.start(applicationContext)
|
||||
startWebView()
|
||||
}
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ class MobileAppIntegrationFragment : Fragment(), MobileAppIntegrationView {
|
|||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
PermissionManager.restartLocationTracking(context!!, activity!!)
|
||||
PermissionManager.restartLocationTracking(context!!)
|
||||
presenter.onFinish()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package io.homeassistant.companion.android.sensors
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import io.homeassistant.companion.android.SensorUpdater
|
||||
import io.homeassistant.companion.android.domain.integration.IntegrationUseCase
|
||||
|
||||
class AllSensorsUpdaterImpl(
|
||||
private val integrationUseCase: IntegrationUseCase,
|
||||
private val appContext: Context
|
||||
) : SensorUpdater {
|
||||
companion object {
|
||||
private const val TAG = "AllSensorsUpdaterImpl"
|
||||
}
|
||||
|
||||
override suspend fun updateSensors() {
|
||||
val sensorManagers = mutableListOf(
|
||||
BatterySensorManager(),
|
||||
NetworkSensorManager()
|
||||
)
|
||||
|
||||
if (integrationUseCase.isBackgroundTrackingEnabled()) {
|
||||
sensorManagers.add(GeocodeSensorManager())
|
||||
}
|
||||
|
||||
registerSensors(sensorManagers)
|
||||
|
||||
val success = integrationUseCase.updateSensors(
|
||||
sensorManagers.flatMap { it.getSensors(appContext) }.toTypedArray()
|
||||
)
|
||||
|
||||
// We failed to update a sensor, we should register all the sensors again.
|
||||
if (!success) {
|
||||
registerSensors(sensorManagers)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun registerSensors(sensorManagers: List<SensorManager>) {
|
||||
|
||||
sensorManagers.flatMap {
|
||||
it.getSensorRegistrations(appContext)
|
||||
}.forEach {
|
||||
// I want to call this async but because of the way we need to store the
|
||||
// fact we have registered it we can't
|
||||
try {
|
||||
integrationUseCase.registerSensor(it)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Issue registering sensor: ${it.uniqueId}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package io.homeassistant.companion.android.sensors
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import io.homeassistant.companion.android.domain.integration.IntegrationUseCase
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class ChargingBroadcastReceiver(
|
||||
private val integrationUseCase: IntegrationUseCase
|
||||
) : BroadcastReceiver() {
|
||||
private val ioScope = CoroutineScope(Dispatchers.IO)
|
||||
private var updateJob: Job? = null
|
||||
override fun onReceive(context: Context, intent: Intent?) {
|
||||
updateJob?.cancel()
|
||||
updateJob = ioScope.launch {
|
||||
AllSensorsUpdaterImpl(integrationUseCase, context).updateSensors()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
package io.homeassistant.companion.android.sensors
|
||||
|
||||
import dagger.Component
|
||||
import io.homeassistant.companion.android.PresenterModule
|
||||
import io.homeassistant.companion.android.common.dagger.AppComponent
|
||||
|
||||
@Component(dependencies = [AppComponent::class])
|
||||
@Component(dependencies = [AppComponent::class], modules = [PresenterModule::class])
|
||||
interface SensorComponent {
|
||||
|
||||
fun inject(worker: SensorWorker)
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
package io.homeassistant.companion.android.sensors
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.ExistingPeriodicWorkPolicy
|
||||
import androidx.work.NetworkType
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import io.homeassistant.companion.android.SensorUpdater
|
||||
import io.homeassistant.companion.android.common.dagger.GraphComponentAccessor
|
||||
import io.homeassistant.companion.android.domain.integration.IntegrationUseCase
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
@ -15,9 +16,10 @@ import javax.inject.Inject
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class SensorWorker(private val appContext: Context, workerParams: WorkerParameters) :
|
||||
CoroutineWorker(appContext, workerParams) {
|
||||
|
||||
class SensorWorker(
|
||||
appContext: Context,
|
||||
workerParams: WorkerParameters
|
||||
) : CoroutineWorker(appContext, workerParams) {
|
||||
companion object {
|
||||
private const val TAG = "SensorWorker"
|
||||
fun start(context: Context) {
|
||||
|
@ -27,61 +29,27 @@ class SensorWorker(private val appContext: Context, workerParams: WorkerParamete
|
|||
val sensorWorker =
|
||||
PeriodicWorkRequestBuilder<SensorWorker>(15, TimeUnit.MINUTES)
|
||||
.setConstraints(constraints)
|
||||
.addTag("sensors")
|
||||
.build()
|
||||
|
||||
WorkManager.getInstance(context).cancelAllWorkByTag("sensors")
|
||||
WorkManager.getInstance(context).enqueue(sensorWorker)
|
||||
WorkManager.getInstance(context).enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.REPLACE, sensorWorker)
|
||||
}
|
||||
}
|
||||
|
||||
@Inject
|
||||
lateinit var integrationUseCase: IntegrationUseCase
|
||||
|
||||
val allSensorUpdater: SensorUpdater
|
||||
|
||||
init {
|
||||
DaggerSensorComponent.builder()
|
||||
.appComponent((appContext as GraphComponentAccessor).appComponent)
|
||||
.build()
|
||||
.inject(this)
|
||||
allSensorUpdater = AllSensorsUpdaterImpl(integrationUseCase, applicationContext)
|
||||
}
|
||||
|
||||
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
|
||||
|
||||
val sensorManagers = arrayListOf(
|
||||
BatterySensorManager(),
|
||||
NetworkSensorManager()
|
||||
)
|
||||
|
||||
if (integrationUseCase.isBackgroundTrackingEnabled()) {
|
||||
sensorManagers.add(GeocodeSensorManager())
|
||||
}
|
||||
|
||||
registerSensors(sensorManagers)
|
||||
|
||||
val success = integrationUseCase.updateSensors(
|
||||
sensorManagers.flatMap { it.getSensors(appContext) }.toTypedArray()
|
||||
)
|
||||
|
||||
// We failed to update a sensor, we should register all the sensors again.
|
||||
if (!success) {
|
||||
registerSensors(sensorManagers)
|
||||
}
|
||||
|
||||
allSensorUpdater.updateSensors()
|
||||
Result.success()
|
||||
}
|
||||
|
||||
private suspend fun registerSensors(sensorManagers: List<SensorManager>) {
|
||||
|
||||
sensorManagers.flatMap {
|
||||
it.getSensorRegistrations(appContext)
|
||||
}.forEach {
|
||||
// I want to call this async but because of the way we need to store the
|
||||
// fact we have registered it we can't
|
||||
try {
|
||||
integrationUseCase.registerSensor(it)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Issue registering sensor: ${it.uniqueId}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import io.homeassistant.companion.android.DaggerPresenterComponent
|
|||
import io.homeassistant.companion.android.PresenterModule
|
||||
import io.homeassistant.companion.android.R
|
||||
import io.homeassistant.companion.android.common.dagger.GraphComponentAccessor
|
||||
import io.homeassistant.companion.android.sensors.SensorWorker
|
||||
import io.homeassistant.companion.android.settings.ssid.SsidDialogFragment
|
||||
import io.homeassistant.companion.android.settings.ssid.SsidPreference
|
||||
import io.homeassistant.companion.android.util.PermissionManager
|
||||
|
@ -96,7 +95,7 @@ class SettingsFragment : PreferenceFragmentCompat(), SettingsView {
|
|||
if (!PermissionManager.hasLocationPermissions(context!!)) {
|
||||
PermissionManager.requestLocationPermissions(this)
|
||||
}
|
||||
PermissionManager.restartLocationTracking(context!!, activity!!)
|
||||
PermissionManager.restartLocationTracking(context!!)
|
||||
}
|
||||
|
||||
override fun disableInternalConnection() {
|
||||
|
@ -111,10 +110,6 @@ class SettingsFragment : PreferenceFragmentCompat(), SettingsView {
|
|||
}
|
||||
}
|
||||
|
||||
override fun restartSensorWorker() {
|
||||
SensorWorker.start(context!!)
|
||||
}
|
||||
|
||||
override fun onDisplayPreferenceDialog(preference: Preference) {
|
||||
if (preference is SsidPreference) {
|
||||
// check if dialog is already showing
|
||||
|
@ -138,7 +133,7 @@ class SettingsFragment : PreferenceFragmentCompat(), SettingsView {
|
|||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
|
||||
if (PermissionManager.validateLocationPermissions(requestCode, permissions, grantResults)) {
|
||||
PermissionManager.restartLocationTracking(context!!, activity!!)
|
||||
PermissionManager.restartLocationTracking(context!!)
|
||||
} else {
|
||||
// If we don't have permissions, don't let them in!
|
||||
findPreference<SwitchPreference>("location_zone")!!.isChecked = false
|
||||
|
|
|
@ -6,6 +6,4 @@ interface SettingsView {
|
|||
fun disableInternalConnection()
|
||||
|
||||
fun enableInternalConnection()
|
||||
|
||||
fun restartSensorWorker()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package io.homeassistant.companion.android.util
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
|
@ -65,11 +64,11 @@ class PermissionManager {
|
|||
fragment.requestPermissions(getLocationPermissionArray(), LOCATION_REQUEST_CODE)
|
||||
}
|
||||
|
||||
fun restartLocationTracking(context: Context, activity: Activity) {
|
||||
fun restartLocationTracking(context: Context) {
|
||||
val intent = Intent(context, LocationBroadcastReceiver::class.java)
|
||||
intent.action = LocationBroadcastReceiver.ACTION_REQUEST_LOCATION_UPDATES
|
||||
|
||||
activity.sendBroadcast(intent)
|
||||
context.sendBroadcast(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ import io.homeassistant.companion.android.R
|
|||
import io.homeassistant.companion.android.background.LocationBroadcastReceiver
|
||||
import io.homeassistant.companion.android.common.dagger.GraphComponentAccessor
|
||||
import io.homeassistant.companion.android.onboarding.OnboardingActivity
|
||||
import io.homeassistant.companion.android.sensors.SensorWorker
|
||||
import io.homeassistant.companion.android.settings.SettingsActivity
|
||||
import io.homeassistant.companion.android.util.PermissionManager
|
||||
import io.homeassistant.companion.android.util.isStarted
|
||||
|
@ -89,7 +88,6 @@ class WebViewActivity : AppCompatActivity(), io.homeassistant.companion.android.
|
|||
val intent = Intent(this, LocationBroadcastReceiver::class.java)
|
||||
intent.action = LocationBroadcastReceiver.ACTION_REQUEST_LOCATION_UPDATES
|
||||
sendBroadcast(intent)
|
||||
SensorWorker.start(applicationContext)
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
WebView.setWebContentsDebuggingEnabled(true)
|
||||
|
|
Loading…
Reference in a new issue