From fc2f4483448a135c810c102092edc16eac1516b4 Mon Sep 17 00:00:00 2001 From: Oliver Zimmerman <oezimmerman@gmail.com> Date: Tue, 14 Jul 2020 15:38:08 +0100 Subject: [PATCH] Implemented a location state within connectivity helper (EXPOSUREAPP-1618) (#853) * Implemented state check for location * formatting * removed duplicate manifest item * Update ConnectivityHelper.kt * Update ConnectivityHelper.kt Co-authored-by: Philipp Woessner <64482866+pwoessner@users.noreply.github.com> --- Corona-Warn-App/src/main/AndroidManifest.xml | 1 + .../storage/SettingsRepository.kt | 10 +++ .../rki/coronawarnapp/ui/main/MainActivity.kt | 15 ++++ .../ui/viewmodel/SettingsViewModel.kt | 11 +++ .../coronawarnapp/util/ConnectivityHelper.kt | 88 +++++++++++++++++++ 5 files changed, 125 insertions(+) diff --git a/Corona-Warn-App/src/main/AndroidManifest.xml b/Corona-Warn-App/src/main/AndroidManifest.xml index c0208b74d..e1533a7fb 100644 --- a/Corona-Warn-App/src/main/AndroidManifest.xml +++ b/Corona-Warn-App/src/main/AndroidManifest.xml @@ -11,6 +11,7 @@ android:required="true" /> <uses-feature android:name="android.hardware.bluetooth" /> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.BLUETOOTH" android:required="true" /> diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SettingsRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SettingsRepository.kt index 5cf13c062..d556fb829 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SettingsRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SettingsRepository.kt @@ -25,6 +25,7 @@ object SettingsRepository { val isManualKeyRetrievalEnabled = MutableLiveData(true) val isConnectionEnabled = MutableLiveData(true) val isBluetoothEnabled = MutableLiveData(true) + val isLocationEnabled = MutableLiveData(true) val isBackgroundJobEnabled = MutableLiveData(true) val isBackgroundPriorityEnabled = MutableLiveData(false) val manualKeyRetrievalTime = MutableLiveData<Long>() @@ -95,6 +96,15 @@ object SettingsRepository { isBluetoothEnabled.postValue(value) } + /** + * Refresh global location state to point out that tracing isn't working + * + * @see ConnectivityHelper + */ + fun updateLocationEnabled(value: Boolean) { + isLocationEnabled.postValue(value) + } + /** * Refresh global bluetooth state to point out that tracing isn't working * diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt index 0abb83ed3..afb0a44be 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt @@ -60,6 +60,19 @@ class MainActivity : AppCompatActivity() { } } + /** + * Register location callback. + */ + private val callbackLocation = object : ConnectivityHelper.LocationCallback() { + override fun onLocationAvailable() { + settingsViewModel.updateLocationEnabled(true) + } + + override fun onLocationUnavailable() { + settingsViewModel.updateLocationEnabled(false) + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) @@ -73,6 +86,7 @@ class MainActivity : AppCompatActivity() { super.onResume() ConnectivityHelper.registerNetworkStatusCallback(this, callbackNetwork) ConnectivityHelper.registerBluetoothStatusCallback(this, callbackBluetooth) + ConnectivityHelper.registerLocationStatusCallback(this, callbackLocation) settingsViewModel.updateBackgroundJobEnabled(ConnectivityHelper.isBackgroundJobEnabled(this)) scheduleWork() } @@ -84,6 +98,7 @@ class MainActivity : AppCompatActivity() { super.onPause() ConnectivityHelper.unregisterNetworkStatusCallback(this, callbackNetwork) ConnectivityHelper.unregisterBluetoothStatusCallback(this, callbackBluetooth) + ConnectivityHelper.unregisterLocationStatusCallback(this, callbackLocation) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SettingsViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SettingsViewModel.kt index c3e32a21d..486954f1a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SettingsViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SettingsViewModel.kt @@ -21,6 +21,8 @@ class SettingsViewModel : ViewModel() { SettingsRepository.isConnectionEnabled val isBluetoothEnabled: LiveData<Boolean> = SettingsRepository.isBluetoothEnabled + val isLocationEnabled: LiveData<Boolean> = + SettingsRepository.isLocationEnabled // Will impact UI if background activity is not permitted, persistent storing is not necessary val isBackgroundJobEnabled: LiveData<Boolean> = SettingsRepository.isBackgroundJobEnabled @@ -100,6 +102,15 @@ class SettingsViewModel : ViewModel() { SettingsRepository.updateBluetoothEnabled(value) } + /** + * Update location enabled + * + * @param value + */ + fun updateLocationEnabled(value: Boolean) { + SettingsRepository.updateLocationEnabled(value) + } + /** * Update background job enabled * diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt index d14c4aa84..907cfc76a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt @@ -6,11 +6,13 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.location.LocationManager import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest import android.os.Build +import androidx.core.location.LocationManagerCompat import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.reporting.report import timber.log.Timber @@ -71,6 +73,63 @@ object ConnectivityHelper { callback.recevier = null } + /** + * Register location state change listener. + * + * @param context the context + * @param callback the location state callback + * + */ + fun registerLocationStatusCallback(context: Context, callback: LocationCallback) { + val receiver = object : BroadcastReceiver() { + var isGpsEnabled: Boolean = false + var isNetworkEnabled: Boolean = false + + override fun onReceive(context: Context, intent: Intent) { + intent.action?.let { act -> + if (act.matches("android.location.PROVIDERS_CHANGED".toRegex())) { + val locationManager = + context.getSystemService(Context.LOCATION_SERVICE) as LocationManager + isGpsEnabled = + locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) + isNetworkEnabled = + locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) + + if (isGpsEnabled || isNetworkEnabled) { + callback.onLocationAvailable() + Timber.d("Location enabled") + } else { + callback.onLocationUnavailable() + Timber.d("Location disabled") + } + } + } + } + } + callback.recevier = receiver + context.registerReceiver( + callback.recevier, + IntentFilter("android.location.PROVIDERS_CHANGED") + ) + // location state doesn't change when you register + if (isLocationEnabled(context)) + callback.onLocationAvailable() + else + callback.onLocationUnavailable() + } + + /** + * Unregister location state change listener. + * + * @param context the context + * @param callback the location state callback + * + */ + fun unregisterLocationStatusCallback(context: Context, callback: LocationCallback) { + context.unregisterReceiver(callback.recevier) + callback.recevier = null + } + /** * Unregister network state change callback. * @@ -158,6 +217,17 @@ object ConnectivityHelper { return bAdapter.isEnabled } + /** + * Get location enabled status. + * + * @return current location status + * + */ + fun isLocationEnabled(context: Context): Boolean { + val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager + return LocationManagerCompat.isLocationEnabled(locationManager) + } + /** * Get network enabled status. * @@ -190,6 +260,24 @@ object ConnectivityHelper { abstract fun onBluetoothUnavailable() } + /** + * Abstract location state change callback. + * + * @see BroadcastReceiver + */ + abstract class LocationCallback { + var recevier: BroadcastReceiver? = null + + /** + * Called when location is turned on. + */ + abstract fun onLocationAvailable() + + /** + * Called when location is turned off. + */ + abstract fun onLocationUnavailable() + } /** * Abstract network state change callback. * -- GitLab