From 8296d1fe1c9024a10b34dfc275798b994ad29e39 Mon Sep 17 00:00:00 2001 From: fynngodau <fynngodau@mailbox.org> Date: Tue, 4 May 2021 11:27:03 +0200 Subject: [PATCH] Support Android 5 (COMMUNITY) (#2955) * Android 5 support * Hide background priority settings on Android 5 Since these settings make no sense there, we are hiding them below Android Marshmellow. * Use AppCompat Toolbar This makes the three-dot menu visible on Android 5 * Fix background color of behavior icons on Android 5 * Fix TAN digits for Android 5 This is a very weird way of doing it, but since Android 5 doesn't support the height attribute, it appears to be the best solution. Via https://stackoverflow.com/a/19239478. * Fix cardTracing style on Android 5 Since this backgroundTint was not applied, simply use the card_dark drawable that already has the color we want. * Remove splash screen on API < 23 Splash screens on Android 5 are very broken, as the images on the splash screen are streched to fit the screen width. Therefore, the splash screen can only be shown on API >= 23. * Remove unused import to fix lint * Fix tests * Undo change to min sdk version This partially reverts commit 2edced1c532ff235fd6d09c8cf19a4a10b491d51. * Small improvements to compat changes * Change BehaviorInfoRow to use ViewCompat call except if on 5.0 * Improve code readability * Move restore non-hacky TAN input drawables for Android >= 6 * Fix drawable files that were placed the wrong way round * Add comments to Android 5 TAN digit assets As suggested by @vaubaehn * Remove unused imports * Use BuildVersionWrap again in NetworkStateProvider This allows mocking the SDK version in tests * Update splash screen * Compat for new code * Fix typo * Don't migrate encrypted shared prefs on API < 23 Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com> Co-authored-by: Mohamed <mohamed.metwalli@sap.com> Co-authored-by: Matthias Urhahn <matthias.urhahn@sap.com> --- .../ui/ContactDiaryTestFragment.kt | 5 +- Corona-Warn-App/src/main/AndroidManifest.xml | 2 +- .../coronawarnapp/CoronaWarnApplication.kt | 8 ++- .../bugreporting/ui/ErrorDialog.kt | 3 +- .../tabs/location/DiaryLocationViewHolder.kt | 5 +- .../details/items/behavior/BehaviorInfoRow.kt | 11 +++- .../ui/calendar/CalendarWeekDayView.kt | 5 +- .../coronawarnapp/ui/main/home/HomeMenu.kt | 2 +- .../settings/start/SettingsBackgroundState.kt | 8 +++ .../ui/submission/tan/TanInput.kt | 5 +- .../coronawarnapp/util/ConnectivityHelper.kt | 15 ++++- .../de/rki/coronawarnapp/util/DialogHelper.kt | 3 +- .../util/device/PowerManagement.kt | 16 ++--- .../util/di/ApplicationComponent.kt | 3 +- .../util/network/NetworkStateProvider.kt | 65 ++++++++++++------- .../main/res/drawable-v23/tan_input_digit.xml | 18 +++++ .../drawable-v23/tan_input_digit_error.xml | 18 +++++ .../src/main/res/drawable/splash_screen.xml | 8 ++- .../src/main/res/drawable/tan_input_digit.xml | 19 ++++-- .../res/drawable/tan_input_digit_error.xml | 20 ++++-- .../src/main/res/layout/fragment_settings.xml | 1 + .../main/res/layout/home_fragment_layout.xml | 4 +- .../src/main/res/values/styles.xml | 3 +- .../coronawarnapp/risk/RiskLevelTaskTest.kt | 7 ++ .../util/network/NetworkStateProviderTest.kt | 2 +- 25 files changed, 188 insertions(+), 68 deletions(-) create mode 100644 Corona-Warn-App/src/main/res/drawable-v23/tan_input_digit.xml create mode 100644 Corona-Warn-App/src/main/res/drawable-v23/tan_input_digit_error.xml diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/contactdiary/ui/ContactDiaryTestFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/contactdiary/ui/ContactDiaryTestFragment.kt index 1fa7e54d4..3cf44a65b 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/contactdiary/ui/ContactDiaryTestFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/contactdiary/ui/ContactDiaryTestFragment.kt @@ -3,6 +3,7 @@ package de.rki.coronawarnapp.test.contactdiary.ui import android.annotation.SuppressLint import android.os.Bundle import android.view.View +import androidx.core.widget.TextViewCompat import androidx.fragment.app.Fragment import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentTestContactDiaryBinding @@ -84,10 +85,10 @@ class ContactDiaryTestFragment : text = duration.toContactDiaryFormat() if (duration.millis == 0L) { setBackgroundResource(R.drawable.contact_diary_duration_background_default) - setTextAppearance(R.style.bodyNeutral) + TextViewCompat.setTextAppearance(this, R.style.bodyNeutral) } else { setBackgroundResource(R.drawable.contact_diary_duration_background_selected) - setTextAppearance(R.style.body1) + TextViewCompat.setTextAppearance(this, R.style.body1) } } } diff --git a/Corona-Warn-App/src/main/AndroidManifest.xml b/Corona-Warn-App/src/main/AndroidManifest.xml index 2fc4b03cb..20dd21fbd 100644 --- a/Corona-Warn-App/src/main/AndroidManifest.xml +++ b/Corona-Warn-App/src/main/AndroidManifest.xml @@ -4,7 +4,7 @@ package="de.rki.coronawarnapp" tools:ignore="LockedOrientationActivity"> - <uses-sdk tools:overrideLibrary="com.google.zxing.client.android" /> + <uses-sdk tools:overrideLibrary="com.google.zxing.client.android,androidx.security" /> <uses-feature android:name="android.hardware.bluetooth_le" diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt index b0c270e62..735cee276 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt @@ -34,11 +34,13 @@ import de.rki.coronawarnapp.risk.execution.ExposureWindowRiskWorkScheduler import de.rki.coronawarnapp.storage.OnboardingSettings import de.rki.coronawarnapp.submission.auto.AutoSubmission import de.rki.coronawarnapp.task.TaskController +import de.rki.coronawarnapp.util.BuildVersionWrap import de.rki.coronawarnapp.util.CWADebug import de.rki.coronawarnapp.util.WatchdogService import de.rki.coronawarnapp.util.device.ForegroundState import de.rki.coronawarnapp.util.di.AppInjector import de.rki.coronawarnapp.util.di.ApplicationComponent +import de.rki.coronawarnapp.util.hasAPILevel import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -87,8 +89,10 @@ class CoronaWarnApplication : Application(), HasAndroidInjector { CWADebug.init(this) AppInjector.init(this).let { compPreview -> - Timber.v("Calling EncryptedPreferencesMigration.doMigration()") - compPreview.encryptedMigration.doMigration() + if (BuildVersionWrap.hasAPILevel(23)) { + Timber.v("Calling EncryptedPreferencesMigration.doMigration()") + compPreview.encryptedMigration.get().doMigration() + } CWADebug.initAfterInjection(compPreview) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/ui/ErrorDialog.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/ui/ErrorDialog.kt index 49e16cef4..c4b4af463 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/ui/ErrorDialog.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/ui/ErrorDialog.kt @@ -6,6 +6,7 @@ import android.text.method.LinkMovementMethod import android.text.util.Linkify import android.widget.TextView import androidx.appcompat.app.AlertDialog +import androidx.core.widget.TextViewCompat import com.google.android.material.dialog.MaterialAlertDialogBuilder import de.rki.coronawarnapp.R import de.rki.coronawarnapp.util.ContextExtensions.getColorStateListCompat @@ -34,7 +35,7 @@ private fun MaterialAlertDialogBuilder.setMessageView( paddingStartEnd, paddingLeftRight ) - setTextAppearance(R.style.body1) + TextViewCompat.setTextAppearance(this, R.style.body1) setLinkTextColor(context.getColorStateListCompat(R.color.button_primary)) setTextIsSelectable(!textHasLinks) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/DiaryLocationViewHolder.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/DiaryLocationViewHolder.kt index 01cc23cd0..ee2d4f701 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/DiaryLocationViewHolder.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/DiaryLocationViewHolder.kt @@ -2,6 +2,7 @@ package de.rki.coronawarnapp.contactdiary.ui.day.tabs.location import android.view.ViewGroup import android.view.accessibility.AccessibilityEvent +import androidx.core.widget.TextViewCompat import de.rki.coronawarnapp.R import de.rki.coronawarnapp.contactdiary.util.hideKeyboard import de.rki.coronawarnapp.contactdiary.util.setClickLabel @@ -48,10 +49,10 @@ class DiaryLocationViewHolder( if (duration == null || duration.millis == 0L) { text = context.getString(R.string.duration_dialog_default_value) setBackgroundResource(R.drawable.contact_diary_duration_background_default) - setTextAppearance(R.style.bodyNeutral) + TextViewCompat.setTextAppearance(this, R.style.bodyNeutral) } else { setBackgroundResource(R.drawable.contact_diary_duration_background_selected) - setTextAppearance(R.style.body1) + TextViewCompat.setTextAppearance(this, R.style.body1) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/items/behavior/BehaviorInfoRow.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/items/behavior/BehaviorInfoRow.kt index 9c7a0c565..e544d8456 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/items/behavior/BehaviorInfoRow.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/items/behavior/BehaviorInfoRow.kt @@ -2,6 +2,8 @@ package de.rki.coronawarnapp.tracing.ui.details.items.behavior import android.content.Context import android.content.res.ColorStateList +import android.graphics.PorterDuff +import android.os.Build import android.util.AttributeSet import android.view.LayoutInflater import android.view.View @@ -14,6 +16,8 @@ import androidx.core.content.withStyledAttributes import androidx.core.view.ViewCompat import androidx.core.widget.ImageViewCompat import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.util.BuildVersionWrap +import de.rki.coronawarnapp.util.hasAPILevel import de.rki.coronawarnapp.util.setUrl class BehaviorInfoRow @JvmOverloads constructor( @@ -61,7 +65,12 @@ class BehaviorInfoRow @JvmOverloads constructor( } fun setBackgroundTint(@ColorInt color: Int) { - ViewCompat.setBackgroundTintList(iconBackground, ColorStateList.valueOf(color)) + when { + BuildVersionWrap.hasAPILevel(Build.VERSION_CODES.LOLLIPOP_MR1) -> + ViewCompat.setBackgroundTintList(iconBackground, ColorStateList.valueOf(color)) + else -> + iconBackground.background.setColorFilter(color, PorterDuff.Mode.SRC_OVER) + } } fun setForegroundTint(@ColorInt color: Int) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/calendar/CalendarWeekDayView.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/calendar/CalendarWeekDayView.kt index 52ff504e3..2b352a1f6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/calendar/CalendarWeekDayView.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/calendar/CalendarWeekDayView.kt @@ -5,6 +5,7 @@ import android.util.AttributeSet import android.view.LayoutInflater import android.widget.LinearLayout import android.widget.TextView +import androidx.core.widget.TextViewCompat import de.rki.coronawarnapp.R /** @@ -43,9 +44,9 @@ class CalendarWeekDayView @JvmOverloads constructor( textView.text = text if (isSelected) { - textView.setTextAppearance(R.style.calendarWeekDaySelected) + TextViewCompat.setTextAppearance(textView, R.style.calendarWeekDaySelected) } else { - textView.setTextAppearance(R.style.calendarWeekDayNormal) + TextViewCompat.setTextAppearance(textView, R.style.calendarWeekDayNormal) } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeMenu.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeMenu.kt index 306b9598a..4189f6bd9 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeMenu.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeMenu.kt @@ -1,7 +1,7 @@ package de.rki.coronawarnapp.ui.main.home import android.view.MenuItem.SHOW_AS_ACTION_ALWAYS -import android.widget.Toolbar +import androidx.appcompat.widget.Toolbar import androidx.navigation.NavController import androidx.navigation.fragment.findNavController import de.rki.coronawarnapp.R diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/start/SettingsBackgroundState.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/start/SettingsBackgroundState.kt index 470cf3234..4217b4972 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/start/SettingsBackgroundState.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/start/SettingsBackgroundState.kt @@ -2,10 +2,13 @@ package de.rki.coronawarnapp.ui.settings.start import android.content.Context import android.graphics.drawable.Drawable +import android.os.Build import androidx.annotation.ColorInt import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.util.BuildVersionWrap import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat import de.rki.coronawarnapp.util.ContextExtensions.getDrawableCompat +import de.rki.coronawarnapp.util.hasAPILevel data class SettingsBackgroundState( val isEnabled: Boolean @@ -34,4 +37,9 @@ data class SettingsBackgroundState( fun getBackgroundPriorityText(c: Context): String = c.getString( if (isEnabled) R.string.settings_on else R.string.settings_off ) + + /** + * Whether the "background priority" row should be visible in the settings + */ + fun showBackgroundPrioritySettings(): Boolean = BuildVersionWrap.hasAPILevel(Build.VERSION_CODES.M) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/tan/TanInput.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/tan/TanInput.kt index 70ceed8db..f71c5e179 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/tan/TanInput.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/tan/TanInput.kt @@ -14,6 +14,7 @@ import androidx.annotation.DimenRes import androidx.core.view.children import androidx.core.widget.doOnTextChanged import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat import de.rki.coronawarnapp.util.getDrawableCompat import java.util.Locale import kotlin.math.max @@ -107,9 +108,9 @@ class TanInput(context: Context, attrs: AttributeSet) : ViewGroup(context, attrs tanDigit.setTextColor( if (Tan.isTanCharacterValid(text)) - resources.getColor(R.color.colorTextPrimary1, null) + context.getColorCompat(R.color.colorTextPrimary1) else - resources.getColor(R.color.colorTextSemanticRed, null) + context.getColorCompat(R.color.colorTextSemanticRed) ) } 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 246ca1e5a..f169b9c7b 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 @@ -5,6 +5,7 @@ import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest +import android.os.Build import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.reporting.report @@ -76,9 +77,17 @@ object ConnectivityHelper { */ fun isNetworkEnabled(context: Context): Boolean { val manager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - val activeNetwork: Network? = manager.activeNetwork - val caps: NetworkCapabilities? = manager.getNetworkCapabilities(activeNetwork) - return caps?.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) ?: false + return when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> { + val activeNetwork = manager.activeNetwork + val caps: NetworkCapabilities? = manager.getNetworkCapabilities(activeNetwork) + caps?.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) ?: false + } + else -> { + val activeNetworkInfo = manager.activeNetworkInfo + activeNetworkInfo != null && activeNetworkInfo.isConnected + } + } } /** diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt index dedb9a57f..9688f3585 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt @@ -6,6 +6,7 @@ import android.text.method.LinkMovementMethod import android.text.util.Linkify import android.widget.TextView import androidx.appcompat.app.AlertDialog +import androidx.core.widget.TextViewCompat import de.rki.coronawarnapp.R import de.rki.coronawarnapp.util.ContextExtensions.getColorStateListCompat import java.util.regex.Pattern @@ -111,7 +112,7 @@ object DialogHelper { textView.linksClickable = true textView.movementMethod = LinkMovementMethod.getInstance() textView.setPadding(paddingStartEnd, paddingLeftRight, paddingStartEnd, paddingLeftRight) - textView.setTextAppearance(R.style.body1) + TextViewCompat.setTextAppearance(textView, R.style.body1) textView.setLinkTextColor(context.getColorStateListCompat(R.color.button_primary)) if (isTextSelectable) textView.setTextIsSelectable(true) return textView diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/device/PowerManagement.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/device/PowerManagement.kt index f022f72dd..294f10ec0 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/device/PowerManagement.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/device/PowerManagement.kt @@ -2,9 +2,10 @@ package de.rki.coronawarnapp.util.device import android.content.Context import android.content.Intent -import android.net.Uri +import android.os.Build import android.os.PowerManager import android.provider.Settings +import androidx.annotation.RequiresApi import androidx.core.content.getSystemService import de.rki.coronawarnapp.util.di.AppContext import javax.inject.Inject @@ -18,14 +19,13 @@ class PowerManagement @Inject constructor( private val powerManager by lazy { context.getSystemService<PowerManager>()!! } val isIgnoringBatteryOptimizations - get() = powerManager.isIgnoringBatteryOptimizations(context.packageName) + get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + powerManager.isIgnoringBatteryOptimizations(context.packageName) + } else { + true + } + @RequiresApi(Build.VERSION_CODES.M) val toBatteryOptimizationSettingsIntent = Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS) - - val disableBatteryOptimizationsIntent = - Intent( - Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, - Uri.parse("package:${context.packageName}") - ) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt index 574ed5dbc..1728ab937 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt @@ -2,6 +2,7 @@ package de.rki.coronawarnapp.util.di import dagger.BindsInstance import dagger.Component +import dagger.Lazy import dagger.android.AndroidInjector import dagger.android.support.AndroidSupportInjectionModule import de.rki.coronawarnapp.CoronaWarnApplication @@ -102,7 +103,7 @@ interface ApplicationComponent : AndroidInjector<CoronaWarnApplication> { fun inject(logger: DebugLogger) - val encryptedMigration: EncryptedPreferencesMigration + val encryptedMigration: Lazy<EncryptedPreferencesMigration> @Component.Factory interface Factory { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/network/NetworkStateProvider.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/network/NetworkStateProvider.kt index 7f06ba7a3..6a550115d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/network/NetworkStateProvider.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/network/NetworkStateProvider.kt @@ -1,5 +1,6 @@ package de.rki.coronawarnapp.util.network +import android.annotation.SuppressLint import android.content.Context import android.net.ConnectivityManager import android.net.LinkProperties @@ -8,6 +9,8 @@ import android.net.NetworkCapabilities import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED import android.os.Build +import androidx.annotation.RequiresApi +import androidx.core.net.ConnectivityManagerCompat import de.rki.coronawarnapp.storage.TestSettings import de.rki.coronawarnapp.util.BuildVersionWrap import de.rki.coronawarnapp.util.coroutine.AppScope @@ -90,34 +93,50 @@ class NetworkStateProvider @Inject constructor( ) private val currentState: State - get() = manager.activeNetwork.let { network -> - State( - activeNetwork = network, - capabilities = network?.let { - try { - manager.getNetworkCapabilities(it) - } catch (e: SecurityException) { - Timber.tag(TAG).e(e, "Failed to determine network capabilities.") - null - } - }, - linkProperties = network?.let { - try { - manager.getLinkProperties(it) - } catch (e: Exception) { - Timber.tag(TAG).e(e, "Failed to determine link properties.") - null - } - }, - isFakeMeteredConnection = testSettings.fakeMeteredConnection.value - ) + @SuppressLint("NewApi") + get() = when { + BuildVersionWrap.hasAPILevel(Build.VERSION_CODES.M) -> api23NetworkState() + else -> { + // Most state information is not available + State( + activeNetwork = null, + capabilities = null, + linkProperties = null, + assumeMeteredConnection = testSettings.fakeMeteredConnection.value || + ConnectivityManagerCompat.isActiveNetworkMetered(manager) + ) + } } + @RequiresApi(Build.VERSION_CODES.M) + private fun api23NetworkState() = manager.activeNetwork.let { network -> + State( + activeNetwork = network, + capabilities = network?.let { + try { + manager.getNetworkCapabilities(it) + } catch (e: SecurityException) { + Timber.tag(TAG).e(e, "Failed to determine network capabilities.") + null + } + }, + linkProperties = network?.let { + try { + manager.getLinkProperties(it) + } catch (e: Exception) { + Timber.tag(TAG).e(e, "Failed to determine link properties.") + null + } + }, + assumeMeteredConnection = testSettings.fakeMeteredConnection.value + ) + } + data class State( val activeNetwork: Network?, val capabilities: NetworkCapabilities?, val linkProperties: LinkProperties?, - private val isFakeMeteredConnection: Boolean = false + private val assumeMeteredConnection: Boolean = false ) { val isMeteredConnection: Boolean get() { @@ -126,7 +145,7 @@ class NetworkStateProvider @Inject constructor( } else { capabilities?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ?: false } - return isFakeMeteredConnection || !unMetered + return assumeMeteredConnection || !unMetered } } diff --git a/Corona-Warn-App/src/main/res/drawable-v23/tan_input_digit.xml b/Corona-Warn-App/src/main/res/drawable-v23/tan_input_digit.xml new file mode 100644 index 000000000..f748bc904 --- /dev/null +++ b/Corona-Warn-App/src/main/res/drawable-v23/tan_input_digit.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item> + <shape android:shape="rectangle"> + <corners android:radius="@dimen/submission_tan_input_digit_radius" /> + <solid android:color="@color/colorSurface2" /> + </shape> + </item> + <item + android:height="@dimen/submission_tan_input_digit_stroke" + android:gravity="bottom"> + <shape android:shape="rectangle"> + <corners android:bottomLeftRadius="@dimen/submission_tan_input_digit_radius" /> + <corners android:bottomRightRadius="@dimen/submission_tan_input_digit_radius" /> + <solid android:color="@color/colorTextSemanticNeutral" /> + </shape> + </item> +</layer-list> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/drawable-v23/tan_input_digit_error.xml b/Corona-Warn-App/src/main/res/drawable-v23/tan_input_digit_error.xml new file mode 100644 index 000000000..8e293e04f --- /dev/null +++ b/Corona-Warn-App/src/main/res/drawable-v23/tan_input_digit_error.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item> + <shape android:shape="rectangle"> + <corners android:radius="@dimen/submission_tan_input_digit_radius" /> + <solid android:color="@color/colorSurface2" /> + </shape> + </item> + <item + android:height="@dimen/submission_tan_input_digit_stroke" + android:gravity="bottom"> + <shape android:shape="rectangle"> + <corners android:bottomLeftRadius="@dimen/submission_tan_input_digit_radius" /> + <corners android:bottomRightRadius="@dimen/submission_tan_input_digit_radius" /> + <solid android:color="@color/colorTextSemanticRed" /> + </shape> + </item> +</layer-list> diff --git a/Corona-Warn-App/src/main/res/drawable/splash_screen.xml b/Corona-Warn-App/src/main/res/drawable/splash_screen.xml index 78d8273a0..f3cffa04d 100644 --- a/Corona-Warn-App/src/main/res/drawable/splash_screen.xml +++ b/Corona-Warn-App/src/main/res/drawable/splash_screen.xml @@ -5,8 +5,10 @@ <item android:drawable="@color/colorBackground" /> <!-- logo --> - <item - android:drawable="@drawable/ic_splash_logo_round" - android:gravity="center" /> + <item> + <bitmap + android:gravity="center" + android:src="@drawable/ic_splash_logo_round" /> + </item> </layer-list> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/drawable/tan_input_digit.xml b/Corona-Warn-App/src/main/res/drawable/tan_input_digit.xml index f748bc904..8b469ff0b 100644 --- a/Corona-Warn-App/src/main/res/drawable/tan_input_digit.xml +++ b/Corona-Warn-App/src/main/res/drawable/tan_input_digit.xml @@ -1,5 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + + <!-- + This asset is only used below Android 6. These Android versions + do not support the `android:height` and `android:width` attributes, + making tricks necessary. + --> + <item> <shape android:shape="rectangle"> <corners android:radius="@dimen/submission_tan_input_digit_radius" /> @@ -7,12 +14,14 @@ </shape> </item> <item - android:height="@dimen/submission_tan_input_digit_stroke" - android:gravity="bottom"> + android:top="-4dp" + android:right="-4dp" + android:left="-4dp"> <shape android:shape="rectangle"> - <corners android:bottomLeftRadius="@dimen/submission_tan_input_digit_radius" /> - <corners android:bottomRightRadius="@dimen/submission_tan_input_digit_radius" /> - <solid android:color="@color/colorTextSemanticNeutral" /> + <stroke + android:width="@dimen/submission_tan_input_digit_stroke" + android:color="@color/colorTextSemanticNeutral" + /> </shape> </item> </layer-list> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/drawable/tan_input_digit_error.xml b/Corona-Warn-App/src/main/res/drawable/tan_input_digit_error.xml index 8e293e04f..93f55158e 100644 --- a/Corona-Warn-App/src/main/res/drawable/tan_input_digit_error.xml +++ b/Corona-Warn-App/src/main/res/drawable/tan_input_digit_error.xml @@ -1,5 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + + <!-- + This asset is only used below Android 6. These Android versions + do not support the `android:height` and `android:width` attributes, + making tricks necessary. + --> + + <item> <shape android:shape="rectangle"> <corners android:radius="@dimen/submission_tan_input_digit_radius" /> @@ -7,12 +15,14 @@ </shape> </item> <item - android:height="@dimen/submission_tan_input_digit_stroke" - android:gravity="bottom"> + android:top="-4dp" + android:right="-4dp" + android:left="-4dp"> <shape android:shape="rectangle"> - <corners android:bottomLeftRadius="@dimen/submission_tan_input_digit_radius" /> - <corners android:bottomRightRadius="@dimen/submission_tan_input_digit_radius" /> - <solid android:color="@color/colorTextSemanticRed" /> + <stroke + android:width="@dimen/submission_tan_input_digit_stroke" + android:color="@color/colorTextSemanticRed" + /> </shape> </item> </layer-list> diff --git a/Corona-Warn-App/src/main/res/layout/fragment_settings.xml b/Corona-Warn-App/src/main/res/layout/fragment_settings.xml index 48388cf27..ff0797231 100644 --- a/Corona-Warn-App/src/main/res/layout/fragment_settings.xml +++ b/Corona-Warn-App/src/main/res/layout/fragment_settings.xml @@ -91,6 +91,7 @@ layout="@layout/include_setting_row" android:layout_width="0dp" android:layout_height="wrap_content" + app:gone="@{!backgroundState.showBackgroundPrioritySettings()}" app:body="@{@string/settings_background_priority_body_description}" app:color="@{backgroundState.getBackgroundPriorityIconColor(context)}" app:icon="@{backgroundState.getBackgroundPriorityIcon(context)}" diff --git a/Corona-Warn-App/src/main/res/layout/home_fragment_layout.xml b/Corona-Warn-App/src/main/res/layout/home_fragment_layout.xml index 683de0e8d..79b703795 100644 --- a/Corona-Warn-App/src/main/res/layout/home_fragment_layout.xml +++ b/Corona-Warn-App/src/main/res/layout/home_fragment_layout.xml @@ -18,7 +18,7 @@ android:orientation="vertical" tools:context=".ui.main.MainActivity"> - <Toolbar + <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -34,7 +34,7 @@ app:srcCompat="@drawable/ic_main_header" bind:cwaContentDescription="@{@string/accessibility_logo}" tools:ignore="ContentDescription" /> - </Toolbar> + </com.google.android.material.appbar.MaterialToolbar> <androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" diff --git a/Corona-Warn-App/src/main/res/values/styles.xml b/Corona-Warn-App/src/main/res/values/styles.xml index bc944522a..dbdaf8ec6 100644 --- a/Corona-Warn-App/src/main/res/values/styles.xml +++ b/Corona-Warn-App/src/main/res/values/styles.xml @@ -251,8 +251,7 @@ <style name="cardTracing"> <item name="android:padding">@dimen/card_padding</item> - <item name="android:background">@drawable/card</item> - <item name="android:backgroundTint">@color/colorSurface2</item> + <item name="android:background">@drawable/card_dark</item> </style> <style name="selectionButton" parent="@style/Widget.AppCompat.Button.Borderless"> diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelTaskTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelTaskTest.kt index b9f84a180..0c6f3fce2 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelTaskTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelTaskTest.kt @@ -4,6 +4,7 @@ import android.content.Context import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities +import android.net.NetworkInfo import de.rki.coronawarnapp.appconfig.AppConfigProvider import de.rki.coronawarnapp.appconfig.ConfigData import de.rki.coronawarnapp.coronatest.CoronaTestRepository @@ -83,6 +84,9 @@ class RiskLevelTaskTest : BaseTest() { every { hasCapability(any()) } returns true } } + every { activeNetworkInfo } returns mockk<NetworkInfo>().apply { + every { isConnected } returns true + } } every { enfClient.isTracingEnabled } returns flowOf(true) @@ -138,6 +142,9 @@ class RiskLevelTaskTest : BaseTest() { every { hasCapability(any()) } returns false } } + every { activeNetworkInfo } returns mockk<NetworkInfo>().apply { + every { isConnected } returns false + } } createTask().run(arguments) shouldBe EwRiskLevelTaskResult( diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/network/NetworkStateProviderTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/network/NetworkStateProviderTest.kt index 6c48eeb1e..76c94e508 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/network/NetworkStateProviderTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/network/NetworkStateProviderTest.kt @@ -198,7 +198,7 @@ class NetworkStateProviderTest : BaseTest() { } @Test - fun `metered connection state can be overriden via test settings`() = runBlockingTest2(ignoreActive = true) { + fun `metered connection state can be overridden via test settings`() = runBlockingTest2(ignoreActive = true) { every { testSettings.fakeMeteredConnection } returns mockFlowPreference(true) val instance = createInstance(this) -- GitLab