Work around rare crashes that can happen when fragments are not attached to a context

while co-routines are still executing but requiring a context

Change-Id: Ie6c7cee50014b59c25384d3bf9a122081b9917fc
This commit is contained in:
Torsten Grote 2021-10-13 14:44:01 -03:00 committed by Marvin W
parent ae8516a339
commit a808476b7d
12 changed files with 56 additions and 35 deletions

View File

@ -31,10 +31,11 @@ class DeviceRegistrationFragment : Fragment(R.layout.device_registration_fragmen
}
fun setEnabled(newStatus: Boolean) {
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
val info = getCheckinServiceInfo(requireContext())
val info = getCheckinServiceInfo(appContext)
val newConfiguration = info.configuration.copy(enabled = newStatus)
setCheckinServiceConfiguration(requireContext(), newConfiguration)
setCheckinServiceConfiguration(appContext, newConfiguration)
displayServiceInfo(info.copy(configuration = newConfiguration))
}
}
@ -45,8 +46,9 @@ class DeviceRegistrationFragment : Fragment(R.layout.device_registration_fragmen
override fun onResume() {
super.onResume()
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
displayServiceInfo(getCheckinServiceInfo(requireContext()))
displayServiceInfo(getCheckinServiceInfo(appContext))
}
}
}

View File

@ -44,8 +44,9 @@ class DeviceRegistrationPreferencesFragment : PreferenceFragmentCompat() {
private fun updateStatus() {
handler.postDelayed(updateRunnable, UPDATE_INTERVAL)
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
val serviceInfo = getCheckinServiceInfo(requireContext())
val serviceInfo = getCheckinServiceInfo(appContext)
statusCategory.isVisible = serviceInfo.configuration.enabled
if (serviceInfo.lastCheckin > 0) {
status.summary = getString(R.string.checkin_last_registration, DateUtils.getRelativeTimeSpanString(serviceInfo.lastCheckin, System.currentTimeMillis(), 0))

View File

@ -32,45 +32,50 @@ class PushNotificationAdvancedFragment : PreferenceFragmentCompat() {
networkOther = preferenceScreen.findPreference(GcmPrefs.PREF_NETWORK_OTHER) ?: networkOther
confirmNewApps.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
if (newValue is Boolean) {
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(confirmNewApps = newValue))
setGcmServiceConfiguration(appContext, getGcmServiceInfo(appContext).configuration.copy(confirmNewApps = newValue))
}
updateContent()
}
true
}
networkMobile.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
(newValue as? String)?.toIntOrNull()?.let {
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(mobile = it))
setGcmServiceConfiguration(appContext, getGcmServiceInfo(appContext).configuration.copy(mobile = it))
}
updateContent()
}
true
}
networkWifi.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
(newValue as? String)?.toIntOrNull()?.let {
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(wifi = it))
setGcmServiceConfiguration(appContext, getGcmServiceInfo(appContext).configuration.copy(wifi = it))
}
updateContent()
}
true
}
networkRoaming.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
(newValue as? String)?.toIntOrNull()?.let {
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(roaming = it))
setGcmServiceConfiguration(appContext, getGcmServiceInfo(appContext).configuration.copy(roaming = it))
}
updateContent()
}
true
}
networkOther.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
(newValue as? String)?.toIntOrNull()?.let {
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(other = it))
setGcmServiceConfiguration(appContext, getGcmServiceInfo(appContext).configuration.copy(other = it))
}
updateContent()
}
@ -84,8 +89,9 @@ class PushNotificationAdvancedFragment : PreferenceFragmentCompat() {
}
private fun updateContent() {
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
val serviceInfo = getGcmServiceInfo(requireContext())
val serviceInfo = getGcmServiceInfo(appContext)
confirmNewApps.isChecked = serviceInfo.configuration.confirmNewApps
networkMobile.value = serviceInfo.configuration.mobile.toString()
networkMobile.summary = getSummaryString(serviceInfo.configuration.mobile, serviceInfo.learntMobileInterval)

View File

@ -52,8 +52,8 @@ class PushNotificationAllAppsFragment : PreferenceFragmentCompat() {
}
private fun updateContent() {
val context = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
val context = requireContext()
val apps = withContext(Dispatchers.IO) {
val res = database.appList.map { app ->
app to context.packageManager.getApplicationInfoIfExists(app.packageName)

View File

@ -46,12 +46,13 @@ class PushNotificationAppFragment : Fragment(R.layout.push_notification_fragment
override fun onResume() {
super.onResume()
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
val pm = requireContext().packageManager
val pm = appContext.packageManager
val applicationInfo = pm.getApplicationInfoIfExists(packageName)
binding.appName = applicationInfo?.loadLabel(pm)?.toString() ?: packageName
binding.appIcon = applicationInfo?.loadIcon(pm)
?: AppCompatResources.getDrawable(requireContext(), android.R.mipmap.sym_def_app_icon)
?: AppCompatResources.getDrawable(appContext, android.R.mipmap.sym_def_app_icon)
}
}
}

View File

@ -30,10 +30,11 @@ class PushNotificationFragment : Fragment(R.layout.push_notification_fragment) {
}
fun setEnabled(newStatus: Boolean) {
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
val info = getGcmServiceInfo(requireContext())
val info = getGcmServiceInfo(appContext)
val newConfiguration = info.configuration.copy(enabled = newStatus)
setGcmServiceConfiguration(requireContext(), newConfiguration)
setGcmServiceConfiguration(appContext, newConfiguration)
displayServiceInfo(info.copy(configuration = newConfiguration))
}
}
@ -44,9 +45,10 @@ class PushNotificationFragment : Fragment(R.layout.push_notification_fragment) {
override fun onResume() {
super.onResume()
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
displayServiceInfo(getGcmServiceInfo(requireContext()))
binding.checkinEnabled = getCheckinServiceInfo(requireContext()).configuration.enabled
displayServiceInfo(getGcmServiceInfo(appContext))
binding.checkinEnabled = getCheckinServiceInfo(appContext).configuration.enabled
}
}

View File

@ -32,10 +32,11 @@ class SafetyNetFragment : Fragment(R.layout.safety_net_fragment) {
}
fun setEnabled(newStatus: Boolean) {
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
val info = getSafetyNetServiceInfo(requireContext())
val info = getSafetyNetServiceInfo(appContext)
val newConfiguration = info.configuration.copy(enabled = newStatus)
displayServiceInfo(setSafetyNetServiceConfiguration(requireContext(), newConfiguration))
displayServiceInfo(setSafetyNetServiceConfiguration(appContext, newConfiguration))
}
}
@ -45,9 +46,10 @@ class SafetyNetFragment : Fragment(R.layout.safety_net_fragment) {
override fun onResume() {
super.onResume()
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
binding.checkinEnabled = getCheckinServiceInfo(requireContext()).configuration.enabled
displayServiceInfo(getSafetyNetServiceInfo(requireContext()))
binding.checkinEnabled = getCheckinServiceInfo(appContext).configuration.enabled
displayServiceInfo(getSafetyNetServiceInfo(appContext))
}
}

View File

@ -5,6 +5,7 @@
package org.microg.gms.ui
import android.content.Context
import android.os.Bundle
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
@ -50,12 +51,13 @@ class SettingsFragment : ResourceSettingsFragment() {
override fun onResume() {
super.onResume()
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
updateDetails()
updateDetails(appContext)
}
}
private suspend fun updateDetails() {
private suspend fun updateDetails(context: Context) {
if (getGcmServiceInfo(requireContext()).configuration.enabled) {
val database = GcmDatabase(context)
val regCount = database.registrationList.size
@ -68,7 +70,7 @@ class SettingsFragment : ResourceSettingsFragment() {
findPreference<Preference>(PREF_CHECKIN)!!.setSummary(if (getCheckinServiceInfo(requireContext()).configuration.enabled) R.string.service_status_enabled_short else R.string.service_status_disabled_short)
findPreference<Preference>(PREF_SNET)!!.setSummary(if (getSafetyNetServiceInfo(requireContext()).configuration.enabled) R.string.service_status_enabled_short else R.string.service_status_disabled_short)
val backendCount = UnifiedLocationClient[requireContext()].getLocationBackends().size + UnifiedLocationClient[requireContext()].getGeocoderBackends().size
val backendCount = UnifiedLocationClient[context].getLocationBackends().size + UnifiedLocationClient[requireContext()].getGeocoderBackends().size
findPreference<Preference>(PREF_UNIFIEDNLP)!!.summary = resources.getQuantityString(R.plurals.pref_unifiednlp_summary, backendCount, backendCount);
findPreference<Preference>(PREF_EXPOSURE)?.isVisible = NearbyPreferencesIntegration.isAvailable

View File

@ -40,12 +40,13 @@ class ExposureNotificationsAppFragment : Fragment(R.layout.exposure_notification
override fun onResume() {
super.onResume()
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
val pm = requireContext().packageManager
val pm = appContext.packageManager
val applicationInfo = pm.getApplicationInfoIfExists(packageName)
binding.appName = applicationInfo?.loadLabel(pm)?.toString() ?: packageName
binding.appIcon = applicationInfo?.loadIcon(pm)
?: AppCompatResources.getDrawable(requireContext(), android.R.mipmap.sym_def_app_icon)
?: AppCompatResources.getDrawable(appContext, android.R.mipmap.sym_def_app_icon)
}
}
}

View File

@ -32,10 +32,11 @@ class ExposureNotificationsFragment : Fragment(R.layout.exposure_notifications_f
}
fun setEnabled(newStatus: Boolean) {
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
val info = getExposureNotificationsServiceInfo(requireContext())
val info = getExposureNotificationsServiceInfo(appContext)
val newConfiguration = info.configuration.copy(enabled = newStatus)
setExposureNotificationsServiceConfiguration(requireContext(), newConfiguration)
setExposureNotificationsServiceConfiguration(appContext, newConfiguration)
displayServiceInfo(info.copy(configuration = newConfiguration))
}
}
@ -46,8 +47,9 @@ class ExposureNotificationsFragment : Fragment(R.layout.exposure_notifications_f
override fun onResume() {
super.onResume()
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
displayServiceInfo(getExposureNotificationsServiceInfo(requireContext()))
displayServiceInfo(getExposureNotificationsServiceInfo(appContext))
}
}
}

View File

@ -101,15 +101,16 @@ class ExposureNotificationsPreferencesFragment : PreferenceFragmentCompat() {
}
private fun updateStatus() {
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
handler.postDelayed(updateStatusRunnable, UPDATE_STATUS_INTERVAL)
val enabled = getExposureNotificationsServiceInfo(requireContext()).configuration.enabled
val enabled = getExposureNotificationsServiceInfo(appContext).configuration.enabled
exposureEnableInfo.isVisible = !enabled
val bluetoothSupported = ScannerService.isSupported(requireContext())
val advertisingSupported = if (bluetoothSupported == true) AdvertiserService.isSupported(requireContext()) else bluetoothSupported
val bluetoothSupported = ScannerService.isSupported(appContext)
val advertisingSupported = if (bluetoothSupported == true) AdvertiserService.isSupported(appContext) else bluetoothSupported
exposureLocationOff.isVisible = enabled && bluetoothSupported != false && !LocationManagerCompat.isLocationEnabled(requireContext().getSystemService(LOCATION_SERVICE) as LocationManager)
exposureLocationOff.isVisible = enabled && bluetoothSupported != false && !LocationManagerCompat.isLocationEnabled(appContext.getSystemService(LOCATION_SERVICE) as LocationManager)
exposureBluetoothOff.isVisible = enabled && bluetoothSupported == null && !turningBluetoothOn
exposureBluetoothUnsupported.isVisible = enabled && bluetoothSupported == false
exposureBluetoothNoAdvertisement.isVisible = enabled && bluetoothSupported == true && advertisingSupported != true
@ -119,9 +120,9 @@ class ExposureNotificationsPreferencesFragment : PreferenceFragmentCompat() {
}
private fun updateContent() {
val context = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
handler.postDelayed(updateContentRunnable, UPDATE_CONTENT_INTERVAL)
val context = requireContext()
val (apps, lastHourKeys, currentId) = ExposureDatabase.with(context) { database ->
val apps = database.appList.map { packageName ->
context.packageManager.getApplicationInfoIfExists(packageName)

View File

@ -72,8 +72,9 @@ class ExposureNotificationsRpisFragment : PreferenceFragmentCompat() {
}
fun updateChart() {
val appContext = requireContext().applicationContext
lifecycleScope.launchWhenResumed {
val rpiHourHistogram = ExposureDatabase.with(requireContext()) { database -> database.rpiHourHistogram }
val rpiHourHistogram = ExposureDatabase.with(appContext) { database -> database.rpiHourHistogram }
val totalRpiCount = rpiHourHistogram.map { it.rpis }.sum()
deleteAll.isEnabled = totalRpiCount > 0
histogramCategory.title = getString(R.string.prefcat_exposure_rpis_histogram_title, totalRpiCount)