From f5364fd5c8b010a70f2f50b414fff2303a894fc0 Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Mon, 7 Mar 2022 17:28:58 +0100 Subject: [PATCH 01/14] Implemented Hibernating Fragment --- .../java/ch/admin/bag/dp3t/MainActivity.kt | 17 +- .../dp3t/hibernate/HibernatingInfoFragment.kt | 64 ++++++ .../admin/bag/dp3t/networking/ConfigWorker.kt | 3 + .../models/ConfigResponseModel.java | 10 + .../admin/bag/dp3t/storage/SecureStorage.java | 20 +- .../res/drawable/ic_shutdown_illu_light.xml | 210 ++++++++++++++++++ .../res/layout/fragment_hibernating_info.xml | 124 +++++++++++ 7 files changed, 443 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt create mode 100644 app/src/main/res/drawable/ic_shutdown_illu_light.xml create mode 100644 app/src/main/res/layout/fragment_hibernating_info.xml diff --git a/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt b/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt index 1fa1ef84..7ff617c8 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt @@ -29,6 +29,7 @@ import ch.admin.bag.dp3t.checkin.networking.CrowdNotifierKeyLoadWorker import ch.admin.bag.dp3t.checkin.utils.CrowdNotifierReminderHelper import ch.admin.bag.dp3t.checkin.utils.ErrorDialog import ch.admin.bag.dp3t.checkin.utils.NotificationHelper +import ch.admin.bag.dp3t.hibernate.HibernatingInfoFragment import ch.admin.bag.dp3t.inform.InformActivity import ch.admin.bag.dp3t.networking.ConfigWorker.Companion.scheduleConfigWorkerIfOutdated import ch.admin.bag.dp3t.onboarding.OnboardingActivityArgs @@ -78,7 +79,7 @@ class MainActivity : FragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - secureStorage.forceUpdateLiveData.observe(this, { + secureStorage.forceUpdateLiveData.observe(this) { val forceUpdate = it && secureStorage.doForceUpdate @@ -96,11 +97,12 @@ class MainActivity : FragmentActivity() { } forceUpdateDialog.show() } - }) + } scheduleConfigWorkerIfOutdated(this) CrowdNotifierKeyLoadWorker.startKeyLoadWorker(this) CrowdNotifierKeyLoadWorker.cleanUpOldData(this) if (savedInstanceState == null) { + val isInHibernatingState = secureStorage.isHibernating val onboardingCompleted = secureStorage.onboardingCompleted val lastShownUpdateBoardingVersion = secureStorage.lastShownUpdateBoardingVersion val instantAppQrCodeUrl = checkForInstantAppUrl() @@ -111,8 +113,9 @@ class MainActivity : FragmentActivity() { lastShownUpdateBoardingVersion < UPDATE_BOARDING_VERSION -> OnboardingType.UPDATE_BOARDING else -> null } - - if (onboardingType == null) { + if (isInHibernatingState) { + showHibernateFragment() + } else if (onboardingType == null) { showHomeFragment() } else { launchOnboarding(onboardingType, instantAppQrCodeUrl) @@ -285,6 +288,12 @@ class MainActivity : FragmentActivity() { startActivity(intent) } + private fun showHibernateFragment() { + supportFragmentManager.beginTransaction() + .add(R.id.main_fragment_container, HibernatingInfoFragment.newInstance()) + .commit() + } + private fun showHomeFragment() { supportFragmentManager.beginTransaction() .add(R.id.main_fragment_container, TabbarHostFragment.newInstance()) diff --git a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt new file mode 100644 index 00000000..5fe7563e --- /dev/null +++ b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt @@ -0,0 +1,64 @@ +package ch.admin.bag.dp3t.hibernate + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.fragment.app.Fragment +import ch.admin.bag.dp3t.R +import ch.admin.bag.dp3t.databinding.FragmentHibernatingInfoBinding +import ch.admin.bag.dp3t.html.HtmlFragment +import ch.admin.bag.dp3t.storage.SecureStorage +import ch.admin.bag.dp3t.util.AssetUtil +import ch.admin.bag.dp3t.util.UrlUtil + +class HibernatingInfoFragment : Fragment() { + + companion object { + @JvmStatic + fun newInstance() = HibernatingInfoFragment() + } + + private val secureStorage by lazy { SecureStorage.getInstance(requireContext()) } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return FragmentHibernatingInfoBinding.inflate(inflater).apply { + + toolbar.setOnMenuItemClickListener { + showImpressum() + true + } + + val infoBoxModel = secureStorage.hibernatingInfoboxCollection?.getInfoBox(resources.getString(R.string.language_key)) + + //TODO: Remove the hardcoded strings from the layout file + infoBoxModel?.let { + title.text = it.title + text.text = it.msg + linkGroup.isVisible = it.urlTitle != null + linkText.text = it.urlTitle + linkGroup.setOnClickListener { v -> UrlUtil.openUrl(requireContext(), it.url) } + } + + }.root + } + + private fun showImpressum() { + val htmlFragment = HtmlFragment.newInstance( + R.string.menu_impressum, AssetUtil.getImpressumBaseUrl(context), + AssetUtil.getImpressumHtml(context) + ) + requireActivity().supportFragmentManager.beginTransaction() + .setCustomAnimations( + R.anim.slide_enter, + R.anim.slide_exit, + R.anim.slide_pop_enter, + R.anim.slide_pop_exit + ) + .replace(R.id.main_fragment_container, htmlFragment) + .addToBackStack(HtmlFragment::class.java.canonicalName) + .commit() + } + +} diff --git a/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt b/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt index f4252f8f..7c83eeaf 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt @@ -77,6 +77,9 @@ class ConfigWorker(context: Context, workerParams: WorkerParameters) : Coroutine val secureStorage = SecureStorage.getInstance(context) secureStorage.doForceUpdate = config.doForceUpdate + secureStorage.isHibernating = config.isDeactivate + secureStorage.hibernatingInfoboxCollection = config.deactivationMessage + secureStorage.setWhatToDoPositiveTestTexts(config.whatToDoPositiveTestTexts) if (config.infoBox != null) { diff --git a/app/src/main/java/ch/admin/bag/dp3t/networking/models/ConfigResponseModel.java b/app/src/main/java/ch/admin/bag/dp3t/networking/models/ConfigResponseModel.java index e6f22d86..1cb57853 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/networking/models/ConfigResponseModel.java +++ b/app/src/main/java/ch/admin/bag/dp3t/networking/models/ConfigResponseModel.java @@ -25,6 +25,8 @@ public class ConfigResponseModel { private VaccinationBookingInfoCollection vaccinationBookingInfo; private boolean showVaccinationInfo; + private boolean deactivate; + private InfoBoxModelCollection deactivationMessage; public boolean getDoForceUpdate() { return forceUpdate; @@ -71,4 +73,12 @@ public boolean isShowVaccinationInfo() { return showVaccinationInfo; } + public boolean isDeactivate() { + return deactivate; + } + + public InfoBoxModelCollection getDeactivationMessage() { + return deactivationMessage; + } + } diff --git a/app/src/main/java/ch/admin/bag/dp3t/storage/SecureStorage.java b/app/src/main/java/ch/admin/bag/dp3t/storage/SecureStorage.java index a7161247..17b14552 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/storage/SecureStorage.java +++ b/app/src/main/java/ch/admin/bag/dp3t/storage/SecureStorage.java @@ -82,6 +82,8 @@ public class SecureStorage { "KEY_POSITIVE_REPORT_OLDEST_SHARED_KEY_OR_CHECKIN"; private static final String KEY_EXPOSURE_NOTIFICATIONS_ACTIVE_BEFORE_ENTERING_COVIDCODE = "KEY_EXPOSURE_NOTIFICATIONS_ACTIVE_BEFORE_ENTERING_COVIDCODE"; + private static final String KEY_IS_IN_HIBERNATING_STATE = "KEY_IS_IN_HIBERNATING_STATE"; + private static final String KEY_HIBERNATING_INFOBOX_MODEL = "KEY_HIBERNATING_INFOBOX_MODEL"; private static SecureStorage instance; @@ -165,6 +167,22 @@ public void setOnboardingCompleted(boolean completed) { prefs.edit().putBoolean(KEY_ONBOARDING_COMPLETED, completed).apply(); } + public boolean isHibernating() { + return prefs.getBoolean(KEY_IS_IN_HIBERNATING_STATE, false); + } + + public void setHibernating(boolean isHibernating) { + prefs.edit().putBoolean(KEY_IS_IN_HIBERNATING_STATE, isHibernating).apply(); + } + + public void setHibernatingInfoboxCollection(InfoBoxModelCollection infoBoxModelCollection) { + prefs.edit().putString(KEY_HIBERNATING_INFOBOX_MODEL, gson.toJson(infoBoxModelCollection)).apply(); + } + + public InfoBoxModelCollection getHibernatingInfoboxCollection() { + return gson.fromJson(prefs.getString(KEY_HIBERNATING_INFOBOX_MODEL, "null"), InfoBoxModelCollection.class); + } + public boolean getOnlyPartialOnboardingCompleted() { return prefs.getBoolean(KEY_ONLY_PARTIAL_ONBOARDING_DONE, false); } @@ -339,7 +357,7 @@ public void setShowVaccinationInfo(boolean showVaccinationInfo) { prefs.edit().putBoolean(KEY_SHOW_VACCINATION_INFO, showVaccinationInfo).apply(); } - public boolean getShowVaccinationInfo(){ + public boolean getShowVaccinationInfo() { return prefs.getBoolean(KEY_SHOW_VACCINATION_INFO, false); } diff --git a/app/src/main/res/drawable/ic_shutdown_illu_light.xml b/app/src/main/res/drawable/ic_shutdown_illu_light.xml new file mode 100644 index 00000000..50dc79d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_shutdown_illu_light.xml @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_hibernating_info.xml b/app/src/main/res/layout/fragment_hibernating_info.xml new file mode 100644 index 00000000..a5fa8431 --- /dev/null +++ b/app/src/main/res/layout/fragment_hibernating_info.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 628d4aa029aba2ba7f718bdb599da1f82e3c8214 Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Tue, 8 Mar 2022 10:29:51 +0100 Subject: [PATCH 02/14] Implemented Hibernating State --- .../java/ch/admin/bag/dp3t/MainActivity.kt | 14 +++++++----- .../ch/admin/bag/dp3t/MainApplication.java | 2 ++ .../CrowdNotifierKeyLoadWorker.java | 4 ++++ .../admin/bag/dp3t/networking/ConfigWorker.kt | 22 +++++++++++++++++-- .../dp3t/util/NotificationRepeatWorker.java | 4 ++++ 5 files changed, 39 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt b/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt index 7ff617c8..d33be0df 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt @@ -79,6 +79,13 @@ class MainActivity : FragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + val isInHibernatingState = secureStorage.isHibernating + if (isInHibernatingState) { + if (savedInstanceState == null) { + showHibernateFragment() + } + return + } secureStorage.forceUpdateLiveData.observe(this) { val forceUpdate = it && secureStorage.doForceUpdate @@ -102,7 +109,6 @@ class MainActivity : FragmentActivity() { CrowdNotifierKeyLoadWorker.startKeyLoadWorker(this) CrowdNotifierKeyLoadWorker.cleanUpOldData(this) if (savedInstanceState == null) { - val isInHibernatingState = secureStorage.isHibernating val onboardingCompleted = secureStorage.onboardingCompleted val lastShownUpdateBoardingVersion = secureStorage.lastShownUpdateBoardingVersion val instantAppQrCodeUrl = checkForInstantAppUrl() @@ -113,9 +119,7 @@ class MainActivity : FragmentActivity() { lastShownUpdateBoardingVersion < UPDATE_BOARDING_VERSION -> OnboardingType.UPDATE_BOARDING else -> null } - if (isInHibernatingState) { - showHibernateFragment() - } else if (onboardingType == null) { + if (onboardingType == null) { showHomeFragment() } else { launchOnboarding(onboardingType, instantAppQrCodeUrl) @@ -177,7 +181,7 @@ class MainActivity : FragmentActivity() { override fun onResume() { super.onResume() - if (secureStorage.onboardingCompleted) checkIntentForActions() + if (secureStorage.onboardingCompleted && !secureStorage.isHibernating) checkIntentForActions() LocalBroadcastManager.getInstance(this) .registerReceiver(autoCheckoutBroadcastReceiver, IntentFilter(CrowdNotifierReminderHelper.ACTION_DID_AUTO_CHECKOUT)) } diff --git a/app/src/main/java/ch/admin/bag/dp3t/MainApplication.java b/app/src/main/java/ch/admin/bag/dp3t/MainApplication.java index 0558a024..188ae174 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/MainApplication.java +++ b/app/src/main/java/ch/admin/bag/dp3t/MainApplication.java @@ -62,6 +62,8 @@ public void onCreate() { FakeWorker.stop(this); } + if (secureStorage.isHibernating()) return; + FakeWorker.safeStartFakeWorker(this); ConfigWorker.scheduleConfigWorkerIfOutdated(this); diff --git a/app/src/main/java/ch/admin/bag/dp3t/checkin/networking/CrowdNotifierKeyLoadWorker.java b/app/src/main/java/ch/admin/bag/dp3t/checkin/networking/CrowdNotifierKeyLoadWorker.java index b5f8d46a..524f8a5a 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/checkin/networking/CrowdNotifierKeyLoadWorker.java +++ b/app/src/main/java/ch/admin/bag/dp3t/checkin/networking/CrowdNotifierKeyLoadWorker.java @@ -46,6 +46,10 @@ public static void startKeyLoadWorker(Context context) { workManager.enqueueUniquePeriodicWork(WORK_TAG, ExistingPeriodicWorkPolicy.KEEP, periodicWorkRequest); } + public static void stop(Context context) { + WorkManager.getInstance(context).cancelAllWorkByTag(WORK_TAG); + } + public CrowdNotifierKeyLoadWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { super(context, workerParams); diff --git a/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt b/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt index 7c83eeaf..3f8e6b4c 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt @@ -20,10 +20,12 @@ import androidx.work.* import ch.admin.bag.dp3t.BuildConfig import ch.admin.bag.dp3t.MainActivity import ch.admin.bag.dp3t.R +import ch.admin.bag.dp3t.checkin.networking.CrowdNotifierKeyLoadWorker import ch.admin.bag.dp3t.debug.DebugFragment import ch.admin.bag.dp3t.networking.errors.ResponseError import ch.admin.bag.dp3t.onboarding.OnboardingSlidePageAdapter.Companion.CHECKIN_UPDATE_BOARDING_VERSION import ch.admin.bag.dp3t.storage.SecureStorage +import ch.admin.bag.dp3t.util.NotificationRepeatWorker import ch.admin.bag.dp3t.util.NotificationUtil import org.dpppt.android.sdk.DP3T import org.dpppt.android.sdk.backend.SignatureException @@ -63,6 +65,10 @@ class ConfigWorker(context: Context, workerParams: WorkerParameters) : Coroutine } } + fun stop(context: Context) { + WorkManager.getInstance(context).cancelAllWorkByTag(FakeWorker.WORK_TAG) + } + @Throws(IOException::class, ResponseError::class, SignatureException::class) private suspend fun loadConfig(context: Context) { val configRepository = ConfigRepository(context) @@ -77,8 +83,6 @@ class ConfigWorker(context: Context, workerParams: WorkerParameters) : Coroutine val secureStorage = SecureStorage.getInstance(context) secureStorage.doForceUpdate = config.doForceUpdate - secureStorage.isHibernating = config.isDeactivate - secureStorage.hibernatingInfoboxCollection = config.deactivationMessage secureStorage.setWhatToDoPositiveTestTexts(config.whatToDoPositiveTestTexts) @@ -114,6 +118,20 @@ class ConfigWorker(context: Context, workerParams: WorkerParameters) : Coroutine showCheckInUpdateNotification(context); } } + + secureStorage.isHibernating = config.isDeactivate + secureStorage.hibernatingInfoboxCollection = config.deactivationMessage + if (config.isDeactivate) { + activateHibernationState(context) + } + } + + private fun activateHibernationState(context: Context) { + DP3T.stop(context) + FakeWorker.stop(context) + CrowdNotifierKeyLoadWorker.stop(context) + NotificationRepeatWorker.stop(context) + this.stop(context) } private fun showNotification(context: Context) { diff --git a/app/src/main/java/ch/admin/bag/dp3t/util/NotificationRepeatWorker.java b/app/src/main/java/ch/admin/bag/dp3t/util/NotificationRepeatWorker.java index 7983fa46..7605a83b 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/util/NotificationRepeatWorker.java +++ b/app/src/main/java/ch/admin/bag/dp3t/util/NotificationRepeatWorker.java @@ -37,6 +37,10 @@ public static void startWorker(Context context) { WorkManager.getInstance(context).enqueueUniqueWork(WORK_TAG, ExistingWorkPolicy.REPLACE, notificationWorker); } + public static void stop(Context context) { + WorkManager.getInstance(context).cancelAllWorkByTag(WORK_TAG); + } + public NotificationRepeatWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { super(context, workerParams); } From 52da78603bdf86da03879a26e44309780d99ff88 Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Thu, 10 Mar 2022 11:59:33 +0100 Subject: [PATCH 03/14] Implemented Config Request in Hibernating State --- .../dp3t/hibernate/HibernatingInfoFragment.kt | 17 ++++++- .../dp3t/hibernate/HibernatingViewModel.kt | 47 +++++++++++++++++++ .../admin/bag/dp3t/networking/ConfigWorker.kt | 2 +- .../res/layout/fragment_hibernating_info.xml | 6 +-- 4 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt diff --git a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt index 5fe7563e..ecd7c420 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt @@ -6,7 +6,9 @@ import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels import ch.admin.bag.dp3t.R +import ch.admin.bag.dp3t.TabbarHostFragment import ch.admin.bag.dp3t.databinding.FragmentHibernatingInfoBinding import ch.admin.bag.dp3t.html.HtmlFragment import ch.admin.bag.dp3t.storage.SecureStorage @@ -20,6 +22,8 @@ class HibernatingInfoFragment : Fragment() { fun newInstance() = HibernatingInfoFragment() } + private val viewModel: HibernatingViewModel by viewModels() + private val secureStorage by lazy { SecureStorage.getInstance(requireContext()) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -32,7 +36,12 @@ class HibernatingInfoFragment : Fragment() { val infoBoxModel = secureStorage.hibernatingInfoboxCollection?.getInfoBox(resources.getString(R.string.language_key)) - //TODO: Remove the hardcoded strings from the layout file + viewModel.isHibernatingModeEnabled.observe(viewLifecycleOwner) { isHibernatingModeEnabled -> + if (!isHibernatingModeEnabled) { + showHomeFragment() + } + } + infoBoxModel?.let { title.text = it.title text.text = it.msg @@ -44,6 +53,12 @@ class HibernatingInfoFragment : Fragment() { }.root } + private fun showHomeFragment() { + requireActivity().supportFragmentManager.beginTransaction() + .replace(R.id.main_fragment_container, TabbarHostFragment.newInstance()) + .commit() + } + private fun showImpressum() { val htmlFragment = HtmlFragment.newInstance( R.string.menu_impressum, AssetUtil.getImpressumBaseUrl(context), diff --git a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt new file mode 100644 index 00000000..259478fa --- /dev/null +++ b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt @@ -0,0 +1,47 @@ +package ch.admin.bag.dp3t.hibernate + +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.viewModelScope +import ch.admin.bag.dp3t.checkin.networking.CrowdNotifierKeyLoadWorker +import ch.admin.bag.dp3t.networking.ConfigWorker +import ch.admin.bag.dp3t.networking.FakeWorker +import ch.admin.bag.dp3t.storage.SecureStorage +import ch.admin.bag.dp3t.util.NotificationRepeatWorker +import kotlinx.coroutines.launch +import org.dpppt.android.sdk.internal.logger.Logger + +class HibernatingViewModel(application: Application) : AndroidViewModel(application) { + + companion object { + private val TAG = "HibernatingViewModel" + + } + + private val isHibernatingModeEnabledMutable = MutableLiveData(true) + val isHibernatingModeEnabled: LiveData = isHibernatingModeEnabledMutable + + init { + loadConfig() + } + + + private fun loadConfig() { + viewModelScope.launch { + try { + ConfigWorker.loadConfig(getApplication()) + if (!SecureStorage.getInstance(getApplication()).isHibernating) { + FakeWorker.safeStartFakeWorker(getApplication()) + CrowdNotifierKeyLoadWorker.startKeyLoadWorker(getApplication()) + NotificationRepeatWorker.startWorker(getApplication()) + ConfigWorker.scheduleConfigWorkerIfOutdated(getApplication()) + isHibernatingModeEnabledMutable.value = false + } + } catch (e: Exception) { + Logger.e(TAG, "config request failed", e) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt b/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt index 3f8e6b4c..1131eb22 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt @@ -70,7 +70,7 @@ class ConfigWorker(context: Context, workerParams: WorkerParameters) : Coroutine } @Throws(IOException::class, ResponseError::class, SignatureException::class) - private suspend fun loadConfig(context: Context) { + suspend fun loadConfig(context: Context) { val configRepository = ConfigRepository(context) val config = configRepository.getConfig(context) diff --git a/app/src/main/res/layout/fragment_hibernating_info.xml b/app/src/main/res/layout/fragment_hibernating_info.xml index a5fa8431..7719128e 100644 --- a/app/src/main/res/layout/fragment_hibernating_info.xml +++ b/app/src/main/res/layout/fragment_hibernating_info.xml @@ -73,7 +73,7 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/spacing_tiny_small" android:gravity="start" - android:text="Der Betrieb der SwissCovid App wurde eingestellt" /> + tools:text="Der Betrieb der SwissCovid App wurde eingestellt" /> + tools:text="Mit der Aufhebung der Massnahmen des Bundes wurde auch der Betrieb der SwissCovid App eingestellt. Wir bitten Sie die App zu deinstallieren und bedanken uns für Ihre Mithilfe. \n\nMit SwissCovid haben Sie einen relevanten Beitrag zur Pandemie-bekämpfung geleistet. Über 168’000 Personen konnten andere schnell über eine mögliches Ansteckungsrisiko informieren und somit Infektionsketten druchbrechen. " /> + tools:text="Und ein externer Link" /> From d5939238bed9a4a42ea89e3b671d396ad410a55d Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Tue, 15 Mar 2022 14:57:31 +0100 Subject: [PATCH 04/14] Perform Config Request during Onboarding to check for hibernating mode --- app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt | 4 +++- .../admin/bag/dp3t/hibernate/HibernatingViewModel.kt | 6 ++++-- .../ch/admin/bag/dp3t/onboarding/OnboardingActivity.kt | 10 ++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt b/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt index d33be0df..ccd613e7 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt @@ -63,7 +63,9 @@ class MainActivity : FragmentActivity() { private val crowdNotifierViewModel: CrowdNotifierViewModel by viewModels() private val onboardingLauncher = registerForActivityResult(OnboardingActivityResultContract()) { - if (it != null) { + if (secureStorage.isHibernating) { + showHibernateFragment() + } else if (it != null) { onOnboardingFinished(it.onboardingType, it.activityResult, it.instantAppUrl) } else { finish() diff --git a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt index 259478fa..2ba45e7b 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt @@ -20,7 +20,7 @@ class HibernatingViewModel(application: Application) : AndroidViewModel(applicat } - private val isHibernatingModeEnabledMutable = MutableLiveData(true) + private val isHibernatingModeEnabledMutable = MutableLiveData() val isHibernatingModeEnabled: LiveData = isHibernatingModeEnabledMutable init { @@ -32,7 +32,9 @@ class HibernatingViewModel(application: Application) : AndroidViewModel(applicat viewModelScope.launch { try { ConfigWorker.loadConfig(getApplication()) - if (!SecureStorage.getInstance(getApplication()).isHibernating) { + if (SecureStorage.getInstance(getApplication()).isHibernating) { + isHibernatingModeEnabledMutable.value = true + } else { FakeWorker.safeStartFakeWorker(getApplication()) CrowdNotifierKeyLoadWorker.startKeyLoadWorker(getApplication()) NotificationRepeatWorker.startWorker(getApplication()) diff --git a/app/src/main/java/ch/admin/bag/dp3t/onboarding/OnboardingActivity.kt b/app/src/main/java/ch/admin/bag/dp3t/onboarding/OnboardingActivity.kt index fd8ef22f..ae37c8d7 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/onboarding/OnboardingActivity.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/onboarding/OnboardingActivity.kt @@ -13,10 +13,12 @@ import android.animation.Animator import android.content.Intent import android.os.Bundle import android.view.View +import androidx.activity.viewModels import androidx.fragment.app.FragmentActivity import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.widget.ViewPager2 import ch.admin.bag.dp3t.R +import ch.admin.bag.dp3t.hibernate.HibernatingViewModel import org.dpppt.android.sdk.DP3T private const val SHOW_SPLASHBOARDING_MILLIS = 3000 @@ -32,10 +34,18 @@ class OnboardingActivity : FragmentActivity() { private lateinit var viewPager: ViewPager2 private lateinit var pagerAdapter: FragmentStateAdapter + private val hibernatingViewModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_onboarding) + hibernatingViewModel.isHibernatingModeEnabled.observe(this) { isHibernatingModeEnabled -> + if (isHibernatingModeEnabled) { + finish() + } + } + splashboarding = findViewById(R.id.splashboarding) viewPager = findViewById(R.id.pager) From 81ed66d494dc1123c5d62621dab9b32ca56b0601 Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Tue, 15 Mar 2022 16:04:10 +0100 Subject: [PATCH 05/14] Prevent SDK from showing notifications to the User --- app/src/main/java/ch/admin/bag/dp3t/MainApplication.java | 7 ++++--- .../ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/ch/admin/bag/dp3t/MainApplication.java b/app/src/main/java/ch/admin/bag/dp3t/MainApplication.java index 188ae174..a57ffe15 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/MainApplication.java +++ b/app/src/main/java/ch/admin/bag/dp3t/MainApplication.java @@ -49,12 +49,15 @@ public void onCreate() { Logger.init(getApplicationContext(), LogLevel.DEBUG); CertificatePinning.initDebug(this); } + SecureStorage secureStorage = SecureStorage.getInstance(this); + + // DP3T SDK is not initialized if app is in Hibernating Mode to prevent it from showing any notifications to the user + if (secureStorage.isHibernating()) return; registerReceiver(contactUpdateReceiver, DP3T.getUpdateIntentFilter()); initDP3T(this); - SecureStorage secureStorage = SecureStorage.getInstance(this); int appVersionCode = BuildConfig.VERSION_CODE; if (secureStorage.getLastKnownAppVersionCode() != appVersionCode) { secureStorage.setLastKnownAppVersionCode(appVersionCode); @@ -62,8 +65,6 @@ public void onCreate() { FakeWorker.stop(this); } - if (secureStorage.isHibernating()) return; - FakeWorker.safeStartFakeWorker(this); ConfigWorker.scheduleConfigWorkerIfOutdated(this); diff --git a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt index 2ba45e7b..95751159 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt @@ -5,12 +5,14 @@ import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope +import ch.admin.bag.dp3t.MainApplication import ch.admin.bag.dp3t.checkin.networking.CrowdNotifierKeyLoadWorker import ch.admin.bag.dp3t.networking.ConfigWorker import ch.admin.bag.dp3t.networking.FakeWorker import ch.admin.bag.dp3t.storage.SecureStorage import ch.admin.bag.dp3t.util.NotificationRepeatWorker import kotlinx.coroutines.launch +import org.dpppt.android.sdk.DP3T import org.dpppt.android.sdk.internal.logger.Logger class HibernatingViewModel(application: Application) : AndroidViewModel(application) { @@ -35,6 +37,7 @@ class HibernatingViewModel(application: Application) : AndroidViewModel(applicat if (SecureStorage.getInstance(getApplication()).isHibernating) { isHibernatingModeEnabledMutable.value = true } else { + MainApplication.initDP3T(getApplication()) FakeWorker.safeStartFakeWorker(getApplication()) CrowdNotifierKeyLoadWorker.startKeyLoadWorker(getApplication()) NotificationRepeatWorker.startWorker(getApplication()) From c6bdca7fd5ba7778facb1056f0727c27c92d50e7 Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Tue, 15 Mar 2022 17:33:22 +0100 Subject: [PATCH 06/14] Update Strings --- .../res/layout/fragment_hibernating_info.xml | 8 +++---- common/src/main/res/values-bs/strings.xml | 15 ++++++++++++ common/src/main/res/values-de/strings.xml | 23 +++++++++++++++++++ common/src/main/res/values-es/strings.xml | 15 ++++++++++++ common/src/main/res/values-fr/strings.xml | 15 ++++++++++++ common/src/main/res/values-hr/strings.xml | 15 ++++++++++++ common/src/main/res/values-it/strings.xml | 15 ++++++++++++ common/src/main/res/values-pt/strings.xml | 15 ++++++++++++ common/src/main/res/values-rm/strings.xml | 15 ++++++++++++ common/src/main/res/values-sq/strings.xml | 15 ++++++++++++ common/src/main/res/values-sr/strings.xml | 15 ++++++++++++ common/src/main/res/values-ti/strings.xml | 15 ++++++++++++ common/src/main/res/values-tr/strings.xml | 15 ++++++++++++ common/src/main/res/values/strings.xml | 15 ++++++++++++ 14 files changed, 207 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/layout/fragment_hibernating_info.xml b/app/src/main/res/layout/fragment_hibernating_info.xml index 7719128e..d1198551 100644 --- a/app/src/main/res/layout/fragment_hibernating_info.xml +++ b/app/src/main/res/layout/fragment_hibernating_info.xml @@ -64,7 +64,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/spacing_larger" - android:text="@string/accessibility_info_button" /> + android:text="@string/termination_header" /> + tools:text="@string/termination_title" /> + tools:text="@string/termination_text" /> + tools:text="@string/termination_link_title" /> diff --git a/common/src/main/res/values-bs/strings.xml b/common/src/main/res/values-bs/strings.xml index 8b5322e6..72f54ebf 100644 --- a/common/src/main/res/values-bs/strings.xml +++ b/common/src/main/res/values-bs/strings.xml @@ -1985,4 +1985,19 @@ Mnoga mesta nude i vakcinaciju bez zakazanog termina" "https://covid19.impf-check.ch/" "Zakažite sada termin" + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values-de/strings.xml b/common/src/main/res/values-de/strings.xml index 6395af93..12ada586 100644 --- a/common/src/main/res/values-de/strings.xml +++ b/common/src/main/res/values-de/strings.xml @@ -2072,4 +2072,27 @@ Viele Orte bieten auch Walk-in-Impfungen ohne Termine an." "https://covid19.impf-check.ch/" "Jetzt Termin buchen" + + + "Information" + + + "Der Betrieb der SwissCovid App wurde eingestellt" + + + "Vielen Dank, dass Sie die SwissCovid App heruntergeladen haben. + +Mit der Verwendung der SwissCovid App haben Sie einen relevanten Beitrag zur Pandemiebekämpfung geleistet. Über 175’000 Personen konnten andere schnell über ein Ansteckungsrisiko informieren und somit Infektionsketten unterbrechen. + +Mit der Aufhebung der Massnahmen des Bundes wurde auch der Betrieb der SwissCovid App eingestellt. Die App ist per sofort inaktiv und soll deinstalliert werden. Sollte eine Reaktivierung aufgrund der epidemiologischen Situation nötig sein, würden wir uns wieder über Ihre Unterstützung freuen." + + + "Vielen Dank, dass Sie die SwissCovid App heruntergeladen haben. + +Mit der Verwendung der SwissCovid App haben Sie einen relevanten Beitrag zur Pandemiebekämpfung geleistet. Über 175’000 Personen konnten andere schnell über ein Ansteckungsrisiko informieren und somit Infektionsketten unterbrechen. + +Mit der Aufhebung der Massnahmen des Bundes wurde auch der Betrieb der SwissCovid App eingestellt. Die App ist per sofort inaktiv und soll deinstalliert werden. Sollte eine Reaktivierung aufgrund der epidemiologischen Situation nötig sein, würden wir uns wieder über Ihre Unterstützung freuen." + + + "Weitere Informationen" \ No newline at end of file diff --git a/common/src/main/res/values-es/strings.xml b/common/src/main/res/values-es/strings.xml index 1666e2dd..bc5e5662 100644 --- a/common/src/main/res/values-es/strings.xml +++ b/common/src/main/res/values-es/strings.xml @@ -1978,4 +1978,19 @@ Muchos centros ofrecen la posibllidad de vacunarse sin cita previa." "https://covid19.impf-check.ch/" "Concierte su cita ahora" + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values-fr/strings.xml b/common/src/main/res/values-fr/strings.xml index 3943c318..d437dce7 100644 --- a/common/src/main/res/values-fr/strings.xml +++ b/common/src/main/res/values-fr/strings.xml @@ -2009,4 +2009,19 @@ Il est aussi possible de se faire vacciner sans rendez-vous dans de nombreux end "https://covid19-vac-check.ch/" "Prendre un rendez-vous maintenant" + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values-hr/strings.xml b/common/src/main/res/values-hr/strings.xml index f7fde2c5..991aeeab 100644 --- a/common/src/main/res/values-hr/strings.xml +++ b/common/src/main/res/values-hr/strings.xml @@ -1983,4 +1983,19 @@ Mnoga mesta nude i vakcinaciju bez zakazanog termina" "https://covid19.impf-check.ch/" "Zakažite sada termin" + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values-it/strings.xml b/common/src/main/res/values-it/strings.xml index c4912a3d..993edb79 100644 --- a/common/src/main/res/values-it/strings.xml +++ b/common/src/main/res/values-it/strings.xml @@ -2018,4 +2018,19 @@ Molti di essi offrono anche vaccinazioni libere senza appuntamento." "https://covid19-vac-check.ch/" "Prendi appuntamento ora" + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values-pt/strings.xml b/common/src/main/res/values-pt/strings.xml index 10041c1b..807f65ab 100644 --- a/common/src/main/res/values-pt/strings.xml +++ b/common/src/main/res/values-pt/strings.xml @@ -1987,4 +1987,19 @@ Muitos lugares também oferecem vacinações Walk-in sem agendamento." "https://covid19.impf-check.ch/" "Agende a data agora" + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values-rm/strings.xml b/common/src/main/res/values-rm/strings.xml index 481f2abf..9e8487b1 100644 --- a/common/src/main/res/values-rm/strings.xml +++ b/common/src/main/res/values-rm/strings.xml @@ -1984,4 +1984,19 @@ Blers lieus porschan er vaccinaziuns «walk-in» senza termin." "https://covid19.impf-check.ch/" "Reservar in termin ussa" + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values-sq/strings.xml b/common/src/main/res/values-sq/strings.xml index 70e0013d..cd4ff0e9 100644 --- a/common/src/main/res/values-sq/strings.xml +++ b/common/src/main/res/values-sq/strings.xml @@ -1989,4 +1989,19 @@ Shumë vende gjithashtu ofrojnë vaksinime pa takim." "https://covid19.impf-check.ch/" "Rezervoni një takim tani" + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values-sr/strings.xml b/common/src/main/res/values-sr/strings.xml index d9088faf..af6ba5ce 100644 --- a/common/src/main/res/values-sr/strings.xml +++ b/common/src/main/res/values-sr/strings.xml @@ -1983,4 +1983,19 @@ Mnoga mesta nude i vakcinaciju bez zakazanog termina" "https://covid19.impf-check.ch/" "Zakažite sada termin" + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values-ti/strings.xml b/common/src/main/res/values-ti/strings.xml index cc06335d..70075cad 100644 --- a/common/src/main/res/values-ti/strings.xml +++ b/common/src/main/res/values-ti/strings.xml @@ -1970,4 +1970,19 @@ SwissCovid ነቶም ኣብቶም ተቓደውቲ ሃገራት ዝተዘርገ "https://covid19.impf-check.ch/" "ሕጂ ቘጸራ ሓዝ" + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values-tr/strings.xml b/common/src/main/res/values-tr/strings.xml index 347a72f3..9aa68d55 100644 --- a/common/src/main/res/values-tr/strings.xml +++ b/common/src/main/res/values-tr/strings.xml @@ -1970,4 +1970,19 @@ Birçok yerde, randevu almadan doğrudan aşı yaptırılabilmektedir." "https://covid19.impf-check.ch/" "Hemen randevu alın" + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index a8152a7d..c3c62981 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -2009,4 +2009,19 @@ Many places also offer walk-in vaccinations without an appointment." "https://covid19.impf-check.ch/" "Book an appointment now" + + + + + + + + + + + + + + + \ No newline at end of file From b2c3baafb3c49d7294a12c626e89e609c2684f70 Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Thu, 17 Mar 2022 10:44:36 +0100 Subject: [PATCH 07/14] Update App Version --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8e2b793f..5d87b0df 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -24,8 +24,8 @@ android { applicationId "ch.admin.bag.dp3t" minSdkVersion 23 targetSdkVersion 30 - versionCode 23010 - versionName "2.3.1" + versionCode 24000 + versionName "2.4.0" resConfigs "en", "fr", "de", "it", "pt", "es", "sq", "bs", "hr", "sr", "rm", "tr", "ti" buildConfigField "long", "BUILD_TIME", readPropertyWithDefault('buildTimestamp', System.currentTimeMillis()) + 'L' From 4830bc245aa1bbb05c4ef7d75f1d24d1fe0fc59e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20R=C3=B6sch?= Date: Thu, 17 Mar 2022 13:12:23 +0100 Subject: [PATCH 08/14] pin only root certificate to be more resistant for changing/expiring certificates --- .../dp3t/networking/CertificatePinning.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/ch/admin/bag/dp3t/networking/CertificatePinning.java b/app/src/main/java/ch/admin/bag/dp3t/networking/CertificatePinning.java index 25b43405..7f8192cf 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/networking/CertificatePinning.java +++ b/app/src/main/java/ch/admin/bag/dp3t/networking/CertificatePinning.java @@ -17,18 +17,18 @@ public class CertificatePinning { private static final CertificatePinner CERTIFICATE_PINNER_LIVE = new CertificatePinner.Builder() - .add("www.pt-d.bfs.admin.ch", "sha256/xWdkLqfT40GnyHyZXt9IStltvrshlowMuGZHgp631Tw=") // leaf - .add("www.pt1-d.bfs.admin.ch", "sha256/Pr8nx8M3Oa8EYefVXYB3D4KJViREDy4ipA1oVyjGoss=") // leaf - .add("codegen-service-d.bag.admin.ch", "sha256/GLV5pALJpJb02GavguT3NTOmOL57H7K3KhJ59iH6A/Q=") //leaf - .add("www.pt-t.bfs.admin.ch", "sha256/KM3iZPSceB+hgYuNI+cSg4LRgTiUxCeGjrfXRQAY6Rs=") // intermediate - .add("www.pt1-t.bfs.admin.ch", "sha256/KM3iZPSceB+hgYuNI+cSg4LRgTiUxCeGjrfXRQAY6Rs=") // intermediate - .add("codegen-service-t.bag.admin.ch", "sha256/KM3iZPSceB+hgYuNI+cSg4LRgTiUxCeGjrfXRQAY6Rs=") // intermediate - .add("www.pt-a.bfs.admin.ch", "sha256/KM3iZPSceB+hgYuNI+cSg4LRgTiUxCeGjrfXRQAY6Rs=") // intermediate - .add("www.pt1-a.bfs.admin.ch", "sha256/KM3iZPSceB+hgYuNI+cSg4LRgTiUxCeGjrfXRQAY6Rs=") // intermediate - .add("codegen-service-a.bag.admin.ch", "sha256/KM3iZPSceB+hgYuNI+cSg4LRgTiUxCeGjrfXRQAY6Rs=") // intermediate - .add("www.pt.bfs.admin.ch", "sha256/KM3iZPSceB+hgYuNI+cSg4LRgTiUxCeGjrfXRQAY6Rs=") // intermediate - .add("www.pt1.bfs.admin.ch", "sha256/KM3iZPSceB+hgYuNI+cSg4LRgTiUxCeGjrfXRQAY6Rs=") // intermediate - .add("codegen-service.bag.admin.ch", "sha256/KM3iZPSceB+hgYuNI+cSg4LRgTiUxCeGjrfXRQAY6Rs=") // intermediate + .add("www.pt-d.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root + .add("www.pt1-d.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root + .add("codegen-service-d.bag.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") //root + .add("www.pt-t.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root + .add("www.pt1-t.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root + .add("codegen-service-t.bag.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root + .add("www.pt-a.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root + .add("www.pt1-a.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root + .add("codegen-service-a.bag.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root + .add("www.pt.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root + .add("www.pt1.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root + .add("codegen-service.bag.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root .build(); private static final CertificatePinner CERTIFICATE_PINNER_DISABLED = new CertificatePinner.Builder().build(); From b8227050c1debb61387ef51efd9cd6fda2e401cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20R=C3=B6sch?= Date: Thu, 17 Mar 2022 13:27:04 +0100 Subject: [PATCH 09/14] extract pin to a constant --- .../dp3t/networking/CertificatePinning.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/ch/admin/bag/dp3t/networking/CertificatePinning.java b/app/src/main/java/ch/admin/bag/dp3t/networking/CertificatePinning.java index 7f8192cf..0f2f04bd 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/networking/CertificatePinning.java +++ b/app/src/main/java/ch/admin/bag/dp3t/networking/CertificatePinning.java @@ -16,19 +16,21 @@ public class CertificatePinning { + public static final String QUOVADIS_ROOT_CA_2_G3_PIN = "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU="; + private static final CertificatePinner CERTIFICATE_PINNER_LIVE = new CertificatePinner.Builder() - .add("www.pt-d.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root - .add("www.pt1-d.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root - .add("codegen-service-d.bag.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") //root - .add("www.pt-t.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root - .add("www.pt1-t.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root - .add("codegen-service-t.bag.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root - .add("www.pt-a.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root - .add("www.pt1-a.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root - .add("codegen-service-a.bag.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root - .add("www.pt.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root - .add("www.pt1.bfs.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root - .add("codegen-service.bag.admin.ch", "sha256/SkntvS+PgjC9VZKzE1c/4cFypF+pgBHMHt27Nq3j/OU=") // root + .add("www.pt-d.bfs.admin.ch", QUOVADIS_ROOT_CA_2_G3_PIN) + .add("www.pt1-d.bfs.admin.ch", QUOVADIS_ROOT_CA_2_G3_PIN) + .add("codegen-service-d.bag.admin.ch", QUOVADIS_ROOT_CA_2_G3_PIN) + .add("www.pt-t.bfs.admin.ch", QUOVADIS_ROOT_CA_2_G3_PIN) + .add("www.pt1-t.bfs.admin.ch", QUOVADIS_ROOT_CA_2_G3_PIN) + .add("codegen-service-t.bag.admin.ch", QUOVADIS_ROOT_CA_2_G3_PIN) + .add("www.pt-a.bfs.admin.ch", QUOVADIS_ROOT_CA_2_G3_PIN) + .add("www.pt1-a.bfs.admin.ch", QUOVADIS_ROOT_CA_2_G3_PIN) + .add("codegen-service-a.bag.admin.ch", QUOVADIS_ROOT_CA_2_G3_PIN) + .add("www.pt.bfs.admin.ch", QUOVADIS_ROOT_CA_2_G3_PIN) + .add("www.pt1.bfs.admin.ch", QUOVADIS_ROOT_CA_2_G3_PIN) + .add("codegen-service.bag.admin.ch", QUOVADIS_ROOT_CA_2_G3_PIN) .build(); private static final CertificatePinner CERTIFICATE_PINNER_DISABLED = new CertificatePinner.Builder().build(); From abb1401837e99aa801f71678b081e82dbdd6ea7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20R=C3=B6sch?= Date: Thu, 17 Mar 2022 15:20:17 +0100 Subject: [PATCH 10/14] translation update --- common/src/main/res/values-bs/strings.xml | 18 +++++++++++++----- common/src/main/res/values-es/strings.xml | 18 +++++++++++++----- common/src/main/res/values-fr/strings.xml | 18 +++++++++++++----- common/src/main/res/values-hr/strings.xml | 18 +++++++++++++----- common/src/main/res/values-it/strings.xml | 18 +++++++++++++----- common/src/main/res/values-pt/strings.xml | 18 +++++++++++++----- common/src/main/res/values-rm/strings.xml | 18 +++++++++++++----- common/src/main/res/values-sq/strings.xml | 18 +++++++++++++----- common/src/main/res/values-sr/strings.xml | 18 +++++++++++++----- common/src/main/res/values-ti/strings.xml | 18 +++++++++++++----- common/src/main/res/values-tr/strings.xml | 18 +++++++++++++----- common/src/main/res/values/strings.xml | 18 +++++++++++++----- 12 files changed, 156 insertions(+), 60 deletions(-) diff --git a/common/src/main/res/values-bs/strings.xml b/common/src/main/res/values-bs/strings.xml index 72f54ebf..2b3dbf20 100644 --- a/common/src/main/res/values-bs/strings.xml +++ b/common/src/main/res/values-bs/strings.xml @@ -1987,17 +1987,25 @@ Mnoga mesta nude i vakcinaciju bez zakazanog termina" "Zakažite sada termin" - + "Informacije" - + "Rad aplikacije SvissCovid je obustavljen" - + "Hvala vam što ste preuzeli aplikaciju SwissCovid. + +Korišćenjem aplikacije SwissCovid dali ste relevantan doprinos u borbi protiv pandemije. Više od 175.000 ljudi bilo je u mogućnosti da brzo informiše druge o riziku od infekcije i tako prekine lance infekcije. + +Ukidanjem saveznih mera obustavljen je i rad aplikacije SwissCovid. Aplikacija je sada neaktivna i trebalo bi da je deinstalirate. Ukoliko bi reaktivacija bila neophodna zbog epidemiološke situacije, ponovo se radujemo vašoj podršci." - + "Hvala vam što ste preuzeli aplikaciju SwissCovid. + +Korišćenjem aplikacije SwissCovid dali ste relevantan doprinos u borbi protiv pandemije. Više od 175.000 ljudi bilo je u mogućnosti da brzo informiše druge o riziku od infekcije i tako prekine lance infekcije. + +Ukidanjem saveznih mera obustavljen je i rad aplikacije SwissCovid. Aplikacija je sada neaktivna i trebalo bi da je deinstalirate. Ukoliko bi reaktivacija bila neophodna zbog epidemiološke situacije, ponovo se radujemo vašoj podršci." - + "Dalje informacije" \ No newline at end of file diff --git a/common/src/main/res/values-es/strings.xml b/common/src/main/res/values-es/strings.xml index bc5e5662..1ca3ce25 100644 --- a/common/src/main/res/values-es/strings.xml +++ b/common/src/main/res/values-es/strings.xml @@ -1980,17 +1980,25 @@ Muchos centros ofrecen la posibllidad de vacunarse sin cita previa." "Concierte su cita ahora" - + "Información" - + "La app SwissCovid ya no está operativa" - + "Muchas gracias por descargar la aplicación SwissCovid. + +Con la utilización de la app SwissCovid ha realizado usted un valioso aporte a la lucha contra la pandemia. Más de 175.000 personas pudieron informar rápidamente a otros de un riesgo de infección e interrumpir así las cadenas de contagio. + +Con la suspensión de las medidas por parte del gobierno federal, también la aplicación SwissCovid deja de estar operativa. La aplicación se ha inactivado y debe ser desinstalada. En caso de que la situación epidemiológica hiciera necesaria su reactivación, nos alegraría contar de nuevo con su apoyo." - + "Muchas gracias por descargar la aplicación SwissCovid. + +Con la utilización de la app SwissCovid ha realizado usted un valioso aporte a la lucha contra la pandemia. Más de 175.000 personas pudieron informar rápidamente a otros de un riesgo de infección e interrumpir así las cadenas de contagio. + +Con la suspensión de las medidas por parte del gobierno federal, también la aplicación SwissCovid deja de estar operativa. La aplicación debe ser desinstalada. En caso de que la situación epidemiológica hiciera necesaria su reactivación, nos alegraría contar de nuevo con su apoyo." - + "Más información" \ No newline at end of file diff --git a/common/src/main/res/values-fr/strings.xml b/common/src/main/res/values-fr/strings.xml index d437dce7..5a13cd0e 100644 --- a/common/src/main/res/values-fr/strings.xml +++ b/common/src/main/res/values-fr/strings.xml @@ -2011,17 +2011,25 @@ Il est aussi possible de se faire vacciner sans rendez-vous dans de nombreux end "Prendre un rendez-vous maintenant" - + "Information" - + "L’application SwissCovid n’est plus en service" - + "Nous vous remercions d’avoir téléchargé l’application SwissCovid. + +En utilisant cette application, vous avez fourni une contribution essentielle à la lutte contre la pandémie. Plus de 175 000 personnes ont pu rapidement informer d’autres d'un risque d’infection et ainsi interrompre les chaînes de transmission. + +Parallèlement à la levée des mesures de la Confédération, l’exploitation de l’application SwissCovid a été suspendue. L’application est inactive dès à présent et doit être désinstallée. Si une réactivation s’avérait nécessaire en raison de la situation épidémiologique, nous serions à nouveau heureux de pouvoir compter sur votre soutien." - + "Nous vous remercions d’avoir téléchargé l’application SwissCovid. + +En utilisant cette application, vous avez fourni une contribution essentielle à la lutte contre la pandémie. Plus de 175 000 personnes ont pu rapidement informer d’autres d'un risque d’infection et ainsi interrompre les chaînes de transmission. + +Parallèlement à la levée des mesures de la Confédération, l’exploitation de l’application SwissCovid a été suspendue. L’application doit être désinstallée. Si une réactivation s’avérait nécessaire en raison de la situation épidémiologique, nous serions à nouveau heureux de pouvoir compter sur votre soutien." - + "Informations complémentaires" \ No newline at end of file diff --git a/common/src/main/res/values-hr/strings.xml b/common/src/main/res/values-hr/strings.xml index 991aeeab..4b80905a 100644 --- a/common/src/main/res/values-hr/strings.xml +++ b/common/src/main/res/values-hr/strings.xml @@ -1985,17 +1985,25 @@ Mnoga mesta nude i vakcinaciju bez zakazanog termina" "Zakažite sada termin" - + "Informacije" - + "Rad aplikacije SvissCovid je obustavljen" - + "Hvala vam što ste preuzeli aplikaciju SwissCovid. + +Korišćenjem aplikacije SwissCovid dali ste relevantan doprinos u borbi protiv pandemije. Više od 175.000 ljudi bilo je u mogućnosti da brzo informiše druge o riziku od infekcije i tako prekine lance infekcije. + +Ukidanjem saveznih mera obustavljen je i rad aplikacije SwissCovid. Aplikacija je sada neaktivna i trebalo bi da je deinstalirate. Ukoliko bi reaktivacija bila neophodna zbog epidemiološke situacije, ponovo se radujemo vašoj podršci." - + "Hvala vam što ste preuzeli aplikaciju SwissCovid. + +Korišćenjem aplikacije SwissCovid dali ste relevantan doprinos u borbi protiv pandemije. Više od 175.000 ljudi bilo je u mogućnosti da brzo informiše druge o riziku od infekcije i tako prekine lance infekcije. + +Ukidanjem saveznih mera obustavljen je i rad aplikacije SwissCovid. Aplikacija je sada neaktivna i trebalo bi da je deinstalirate. Ukoliko bi reaktivacija bila neophodna zbog epidemiološke situacije, ponovo se radujemo vašoj podršci." - + "Dalje informacije" \ No newline at end of file diff --git a/common/src/main/res/values-it/strings.xml b/common/src/main/res/values-it/strings.xml index 993edb79..1f43dd25 100644 --- a/common/src/main/res/values-it/strings.xml +++ b/common/src/main/res/values-it/strings.xml @@ -2020,17 +2020,25 @@ Molti di essi offrono anche vaccinazioni libere senza appuntamento." "Prendi appuntamento ora" - + "Informazione" - + "Il funzionamento dell'app SwissCovid è stato sospeso" - + "Grazie per aver scaricato l'app SwissCovid. + +Utilizzando l'app SwissCovid hai fornito un contributo rilevante alla lotta alla pandemia. Oltre 175 000 persone hanno potuto informare gli altri rapidamente di un rischio di contagio, interrompendo così le catene di infezione. + +Con l'abrogazione dei provvedimenti della Confederazione, anche il funzionamento dell'app SwissCovid è stato sospeso. L'app è inattiva da subito e deve essere disinstallata. Se la situazione epidemiologica dovesse rendere necessaria una riattivazione, saremmo lieti di poter contare nuovamente sul tuo sostegno." - + "Grazie per aver scaricato l'app SwissCovid. + +Utilizzando l'app SwissCovid hai fornito un contributo rilevante alla lotta alla pandemia. Oltre 175 000 persone hanno potuto informare gli altri rapidamente di un rischio di contagio, interrompendo così le catene di infezione. + +Con l'abrogazione dei provvedimenti della Confederazione, anche il funzionamento dell'app SwissCovid è stato sospeso. L'app deve essere disinstallata. Se la situazione epidemiologica dovesse rendere necessaria una riattivazione, saremmo lieti di poter contare nuovamente sul tuo sostegno." - + "Ulteriori informazioni" \ No newline at end of file diff --git a/common/src/main/res/values-pt/strings.xml b/common/src/main/res/values-pt/strings.xml index 807f65ab..4a9c6971 100644 --- a/common/src/main/res/values-pt/strings.xml +++ b/common/src/main/res/values-pt/strings.xml @@ -1989,17 +1989,25 @@ Muitos lugares também oferecem vacinações Walk-in sem agendamento." "Agende a data agora" - + "Informação" - + "A operação do aplicativo SwissCovid cessou" - + "Agradecemos ter baixado o aplicativo SwissCovid. + +Com a utilização do aplicativo você prestou um contributo relevante para o combate à pandemia. Mais de 175.000 pessoas puderam informar outros rapidamente sobre um risco de contágio e interromper as cadeias de infeção. + +Com a revogação das medidas da Confederação, a operação do aplicativo SwissCovid também cessou. A partir de agora, o aplicativo é inativo e deve ser desinstalado. Se uma reativação for necessária devido à situação epidemiológica, seríamos muito grato pela sua ajuda." - + "Agradecemos ter baixado o aplicativo SwissCovid. + +Com a utilização do aplicativo você prestou um contributo relevante para o combate à pandemia. Mais de 175.000 pessoas puderam informar outros rapidamente sobre um risco de contágio e interromper as cadeias de infeção. + +Com a revogação das medidas da Confederação, a operação do aplicativo SwissCovid também cessou. A partir de agora, o aplicativo é inativo e deve ser desinstalado. Se uma reativação for necessária devido à situação epidemiológica, seríamos muito grato pela sua ajuda." - + "Mais informações" \ No newline at end of file diff --git a/common/src/main/res/values-rm/strings.xml b/common/src/main/res/values-rm/strings.xml index 9e8487b1..86259bd6 100644 --- a/common/src/main/res/values-rm/strings.xml +++ b/common/src/main/res/values-rm/strings.xml @@ -1986,17 +1986,25 @@ Blers lieus porschan er vaccinaziuns «walk-in» senza termin." "Reservar in termin ussa" - + "Infurmaziun" - + "Il manaschi da l'app SwissCovid è vegnì terminà." - + "Grazia fitg che Vus avais chargià giu l'app SwissCovid. + +Cun duvrar l'app SwissCovid avais Vus prestà ina contribuziun impurtanta en il cumbat cunter la pandemia. Passa 175 000 persunas han pudì infurmar autras persunas davart ina ristga d'infecziun ed han uschia pudì interrumper chadainas d'infecziun. + +Cun l'aboliziun da las mesiras da la Confederaziun è er vegnì terminà il manaschi da l'app SwissCovid. L'app è per immediat inactiva e duai vegnir deinstallada. Sch'ella stuess puspè vegnir activada causa la situaziun epidemiologica, ans legrassan nus puspè da Voss sustegn." - + "Grazia fitg che Vus avais chargià giu l'app SwissCovid. + +Cun duvrar l'app SwissCovid avais Vus prestà ina contribuziun impurtanta en il cumbat cunter la pandemia. Passa 175 000 persunas han pudì infurmar autras persunas davart ina ristga d'infecziun ed han uschia pudì interrumper chadainas d'infecziun. + +Cun l'aboliziun da las mesiras da la Confederaziun è er vegnì terminà il manaschi da l'app SwissCovid. L'app duai vegnir deinstallada. Sch'ella stuess puspè vegnir activada causa la situaziun epidemiologica, ans legrassan nus puspè da Voss sustegn." - + "Ulteriuras infurmaziuns" \ No newline at end of file diff --git a/common/src/main/res/values-sq/strings.xml b/common/src/main/res/values-sq/strings.xml index cd4ff0e9..1e3f5520 100644 --- a/common/src/main/res/values-sq/strings.xml +++ b/common/src/main/res/values-sq/strings.xml @@ -1991,17 +1991,25 @@ Shumë vende gjithashtu ofrojnë vaksinime pa takim." "Rezervoni një takim tani" - + "Informacion" - + "Funksionimi i aplikacionit “SwissCovid” u ndërpre" - + "Faleminderit shumë, që ju e keni shkarkuar aplikacionin “SwissCovid”. + +Me përdorimin e aplikacionin “SwissCovid” ju keni dhënë një kontribut të spikatshëm për luftimin e pandemisë. Mbi 175’000 persona mundën të informonin shpejt të tjerët mbi një rrezik infektimi dhe të ndërprisnin me këtë zinxhirin e infektimit. + +Me shfuqizimin e masave të federatës u ndërpre edhe funksionimi i aplikacionit “SwissCovid”. Aplikacioni është menjëherë joveprues dhe duhet të deinstalohet. Nëse për shkak të situatës epidemiologjike do të jetë i nevojshëm një riaktivizim, ne do të gëzoheshim përsëri për mbështetjen tuaj." - + "Faleminderit shumë, që ju e keni shkarkuar aplikacionin “SwissCovid”. + +Me përdorimin e aplikacionin “SwissCovid” ju keni dhënë një kontribut të spikatshëm për luftimin e pandemisë. Mbi 175’000 persona mundën të informonin shpejt të tjerët mbi një rrezik infektimi dhe të ndërprisnin me këtë zinxhirin e infektimit. + +Me shfuqizimin e masave të federatës u ndërpre edhe funksionimi i aplikacionit “SwissCovid”. Aplikacioni duhet të deinstalohet. Nëse për shkak të situatës epidemiologjike do të jetë i nevojshëm një riaktivizim, ne do të gëzoheshim përsëri për mbështetjen tuaj." - + "Informacione të tjera" \ No newline at end of file diff --git a/common/src/main/res/values-sr/strings.xml b/common/src/main/res/values-sr/strings.xml index af6ba5ce..c584372e 100644 --- a/common/src/main/res/values-sr/strings.xml +++ b/common/src/main/res/values-sr/strings.xml @@ -1985,17 +1985,25 @@ Mnoga mesta nude i vakcinaciju bez zakazanog termina" "Zakažite sada termin" - + "Informacije" - + "Rad aplikacije SvissCovid je obustavljen" - + "Hvala vam što ste preuzeli aplikaciju SwissCovid. + +Korišćenjem aplikacije SwissCovid dali ste relevantan doprinos u borbi protiv pandemije. Više od 175.000 ljudi bilo je u mogućnosti da brzo informiše druge o riziku od infekcije i tako prekine lance infekcije. + +Ukidanjem saveznih mera obustavljen je i rad aplikacije SwissCovid. Aplikacija je sada neaktivna i trebalo bi da je deinstalirate. Ukoliko bi reaktivacija bila neophodna zbog epidemiološke situacije, ponovo se radujemo vašoj podršci." - + "Hvala vam što ste preuzeli aplikaciju SwissCovid. + +Korišćenjem aplikacije SwissCovid dali ste relevantan doprinos u borbi protiv pandemije. Više od 175.000 ljudi bilo je u mogućnosti da brzo informiše druge o riziku od infekcije i tako prekine lance infekcije. + +Ukidanjem saveznih mera obustavljen je i rad aplikacije SwissCovid. Aplikacija je sada neaktivna i trebalo bi da je deinstalirate. Ukoliko bi reaktivacija bila neophodna zbog epidemiološke situacije, ponovo se radujemo vašoj podršci." - + "Dalje informacije" \ No newline at end of file diff --git a/common/src/main/res/values-ti/strings.xml b/common/src/main/res/values-ti/strings.xml index 70075cad..6c42d57f 100644 --- a/common/src/main/res/values-ti/strings.xml +++ b/common/src/main/res/values-ti/strings.xml @@ -1972,17 +1972,25 @@ SwissCovid ነቶም ኣብቶም ተቓደውቲ ሃገራት ዝተዘርገ "ሕጂ ቘጸራ ሓዝ" - + "ሓበሬታ" - + "ኣሰራርሓ እቲ SwissCovid ዚብሃል ኣፕሊኬሽን ተቛሪጹ እዩ።" - + "ነቲ ስዊዝኮቪድ ዚብሃል ኣፕሊኬሽን ስለ ዘራገፍኩምልና (ዳውንሎውድ ብምግባርኩም) አመስግነኩም። + +ነቲ ስዊዝኮቪድ ዚብሃል ኣፕሊኬሽን ተጠቒምካ ነዚ ለብዒ እዚ ንምቅላስ ኣገዳሲ ኣበርክቶ ጌርካ ኢኻ። ልዕሊ 175,000 ዝዀኑ ሰባት ንኻልኦት ሰባት ብዛዕባ እቲ ኼጋጥም ዚኽእል ረኽሲ ቐልጢፎም ኪነግርዎም ንሰንሰለት እቲ ረኽሲ ድማ ኬቋርጽዎ ኽኢሎም እዮም። + +እቲ ፈደራላዊ መንግስቲ ዝወሰዶ ስጕምትታት ምስ ተደምሰሰ ኣሰራርሓ እቲ ስዊዝኮቪድ ዚብሃል ኣፕሊኬሽን እውን ተቛረጸ። እቲ ኣፕሊኬሽን ብኡንብኡ ዘይንጡፍ ስለ ዝዀነ ኪቕመጥ ኣለዎ። ብሰንኪ እቲ ለብዒ እንደገና ምላሽ ምሃብ ኣድላዪ እንተ ዀይኑ እንደገና ደገፍካ ኽንረክብ ሕጉሳት ኢና ።" - + "ነቲ ስዊዝኮቪድ ዚብሃል ኣፕሊኬሽን ስለ ዘራገፍኩምልና (ዳውንሎውድ ብምግባርኩም) አመስግነኩም። + +ነቲ ስዊዝኮቪድ ዚብሃል ኣፕሊኬሽን ተጠቒምካ ነዚ ለብዒ እዚ ንምቅላስ ኣገዳሲ ኣበርክቶ ጌርካ ኢኻ። ልዕሊ 175,000 ዝዀኑ ሰባት ንኻልኦት ሰባት ብዛዕባ እቲ ኼጋጥም ዚኽእል ረኽሲ ቐልጢፎም ኪነግርዎም ንሰንሰለት እቲ ረኽሲ ድማ ኬቋርጽዎ ኽኢሎም እዮም። + +እቲ ፈደራላዊ መንግስቲ ዝወሰዶ ስጕምትታት ምስ ተደምሰሰ ኣሰራርሓ እቲ ስዊዝኮቪድ ዚብሃል ኣፕሊኬሽን እውን ተቛረጸ። እቲ ኣፕሊኬሽን ኪገጣጠም ኣለዎ። ብሰንኪ እቲ ለብዒ እንደገና ምላሽ ምሃብ ኣድላዪ እንተ ዀይኑ እንደገና ደገፍካ ኽንረክብ ሕጉሳት ኢና።" - + "ዝያዳ ሓበሬታ" \ No newline at end of file diff --git a/common/src/main/res/values-tr/strings.xml b/common/src/main/res/values-tr/strings.xml index 9aa68d55..df33778c 100644 --- a/common/src/main/res/values-tr/strings.xml +++ b/common/src/main/res/values-tr/strings.xml @@ -1972,17 +1972,25 @@ Birçok yerde, randevu almadan doğrudan aşı yaptırılabilmektedir." "Hemen randevu alın" - + "Bilgilendirme" - + "SwissCovid uygulaması devre dışı bırakıldı" - + "SwissCovid uygulamasını yüklediğiniz için çok teşekkür ederiz. + +SwissCovid uygulamasını kullanmakla pandemiyle mücadeleye önemli bir katkı sağlamış oldunuz. Sayıları 175’000'i geçen kişi bulaşma riski konusunda diğerlerini hızlı bir şekilde bilgilendirme imkânına sahip oldu ve dolayısıyla enfeksiyon zincirini kesintiye uğratabildi. + +Federal resmi makamların önlemleri kaldırmasıyla birlikte SwissCovid uygulaması da devre dışı bırakıldı. Bu uygulama şu andan itibaren aktif durumda değildir ve silinmesi gerekmektedir. Epidemiyolojik durum bunun yeniden aktif hale getirilmesini gerekli kılarsa yine destek sağlamanıza seviniriz." - + "SwissCovid uygulamasını yüklediğiniz için çok teşekkür ederiz. + +SwissCovid uygulamasını kullanmakla pandemiyle mücadeleye önemli bir katkı sağlamış oldunuz. Sayıları 175’000'i geçen kişi bulaşma riski konusunda diğerlerini hızlı bir şekilde bilgilendirme imkânına sahip oldu ve dolayısıyla enfeksiyon zincirini kesintiye uğratabildi. + +Federal resmi makamların önlemleri kaldırmasıyla birlikte SwissCovid uygulaması da devre dışı bırakıldı. Uygulamanın silinmesi gerekmektedir. Epidemiyolojik durum bunun yeniden aktif hale getirilmesini gerekli kılarsa yine destek sağlamanıza seviniriz." - + "Daha fazla bilgi" \ No newline at end of file diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index c3c62981..ea80ba0e 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -2011,17 +2011,25 @@ Many places also offer walk-in vaccinations without an appointment." "Book an appointment now" - + "Information" - + "The SwissCovid app has been discontinued" - + "Thank you for downloading the SwissCovid app. + +You have made an important contribution to fighting the pandemic by using the SwissCovid app. More than 175,000 people were able to break the transmission chain by quickly informing others of the risk of infection. + +The SwissCovid app was discontinued when the federal government's other measures were lifted. The app is now inactive and you should delete it. We hope we can count on your support again if the epidemiological situation should require its reactivation in the future." - + "Thank you for downloading the SwissCovid app. + +You have made an important contribution to fighting the pandemic by using the SwissCovid app. More than 175,000 people were able to break the transmission chain by quickly informing others of the risk of infection. + +The SwissCovid app was discontinued when the federal government's other measures were lifted, and it should now be deleted. We hope we can count on your support again if the epidemiological situation should require its reactivation in the future." - + "Further information" \ No newline at end of file From d74466868459984b733bdbfb19bf8d3ddca0a91d Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Thu, 17 Mar 2022 16:48:38 +0100 Subject: [PATCH 11/14] Observe Infobox Content in Hibernate Fragment --- .../bag/dp3t/hibernate/HibernatingInfoFragment.kt | 8 ++------ .../admin/bag/dp3t/hibernate/HibernatingViewModel.kt | 12 +++++++++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt index ecd7c420..623d7811 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt @@ -11,7 +11,6 @@ import ch.admin.bag.dp3t.R import ch.admin.bag.dp3t.TabbarHostFragment import ch.admin.bag.dp3t.databinding.FragmentHibernatingInfoBinding import ch.admin.bag.dp3t.html.HtmlFragment -import ch.admin.bag.dp3t.storage.SecureStorage import ch.admin.bag.dp3t.util.AssetUtil import ch.admin.bag.dp3t.util.UrlUtil @@ -24,8 +23,6 @@ class HibernatingInfoFragment : Fragment() { private val viewModel: HibernatingViewModel by viewModels() - private val secureStorage by lazy { SecureStorage.getInstance(requireContext()) } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return FragmentHibernatingInfoBinding.inflate(inflater).apply { @@ -34,20 +31,19 @@ class HibernatingInfoFragment : Fragment() { true } - val infoBoxModel = secureStorage.hibernatingInfoboxCollection?.getInfoBox(resources.getString(R.string.language_key)) - viewModel.isHibernatingModeEnabled.observe(viewLifecycleOwner) { isHibernatingModeEnabled -> if (!isHibernatingModeEnabled) { showHomeFragment() } } - infoBoxModel?.let { + viewModel.hibernatingInfoBox.observe(viewLifecycleOwner) { title.text = it.title text.text = it.msg linkGroup.isVisible = it.urlTitle != null linkText.text = it.urlTitle linkGroup.setOnClickListener { v -> UrlUtil.openUrl(requireContext(), it.url) } + } }.root diff --git a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt index 95751159..acb84419 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt @@ -6,9 +6,12 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import ch.admin.bag.dp3t.MainApplication +import ch.admin.bag.dp3t.R import ch.admin.bag.dp3t.checkin.networking.CrowdNotifierKeyLoadWorker import ch.admin.bag.dp3t.networking.ConfigWorker import ch.admin.bag.dp3t.networking.FakeWorker +import ch.admin.bag.dp3t.networking.models.InfoBoxModel +import ch.admin.bag.dp3t.networking.models.InfoBoxModelCollection import ch.admin.bag.dp3t.storage.SecureStorage import ch.admin.bag.dp3t.util.NotificationRepeatWorker import kotlinx.coroutines.launch @@ -25,6 +28,12 @@ class HibernatingViewModel(application: Application) : AndroidViewModel(applicat private val isHibernatingModeEnabledMutable = MutableLiveData() val isHibernatingModeEnabled: LiveData = isHibernatingModeEnabledMutable + private val hibernatingInfoboxMutable = MutableLiveData() + val hibernatingInfoBox: LiveData = hibernatingInfoboxMutable + + private val secureStorage: SecureStorage by lazy { SecureStorage.getInstance(application) } + private val languageKey = application.getString(R.string.language_key) + init { loadConfig() } @@ -34,8 +43,9 @@ class HibernatingViewModel(application: Application) : AndroidViewModel(applicat viewModelScope.launch { try { ConfigWorker.loadConfig(getApplication()) - if (SecureStorage.getInstance(getApplication()).isHibernating) { + if (secureStorage.isHibernating) { isHibernatingModeEnabledMutable.value = true + hibernatingInfoboxMutable.value = secureStorage.hibernatingInfoboxCollection?.getInfoBox(languageKey) } else { MainApplication.initDP3T(getApplication()) FakeWorker.safeStartFakeWorker(getApplication()) From 3e1460d0b1c7b0403e0d757ba79e03df3815e301 Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Thu, 17 Mar 2022 17:13:20 +0100 Subject: [PATCH 12/14] Fix issues caused by uninitialized DP3T SDK in Hibernating State --- .../dp3t/hibernate/HibernatingViewModel.kt | 8 +++++--- .../bag/dp3t/networking/ConfigRepository.kt | 9 ++++++++- .../admin/bag/dp3t/networking/ConfigWorker.kt | 19 ++++++++++++------- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt index acb84419..3e036978 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt @@ -28,12 +28,14 @@ class HibernatingViewModel(application: Application) : AndroidViewModel(applicat private val isHibernatingModeEnabledMutable = MutableLiveData() val isHibernatingModeEnabled: LiveData = isHibernatingModeEnabledMutable - private val hibernatingInfoboxMutable = MutableLiveData() - val hibernatingInfoBox: LiveData = hibernatingInfoboxMutable - private val secureStorage: SecureStorage by lazy { SecureStorage.getInstance(application) } private val languageKey = application.getString(R.string.language_key) + private val hibernatingInfoboxMutable = + MutableLiveData(secureStorage.hibernatingInfoboxCollection?.getInfoBox(languageKey)) + val hibernatingInfoBox: LiveData = hibernatingInfoboxMutable + + init { loadConfig() } diff --git a/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigRepository.kt b/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigRepository.kt index 0131a573..9e58bd69 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigRepository.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigRepository.kt @@ -24,6 +24,7 @@ import org.dpppt.android.sdk.util.SignatureUtil import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import java.io.IOException +import java.lang.Exception class ConfigRepository(context: Context) { @@ -64,7 +65,13 @@ class ConfigRepository(context: Context) { val appVersion = APP_VERSION_PREFIX_ANDROID + BuildConfig.VERSION_NAME val osVersion = OS_VERSION_PREFIX_ANDROID + Build.VERSION.SDK_INT val buildNumber = BuildConfig.BUILD_TIME.toString() - val enModuleVersion = DP3T.getENModuleVersion(context).toString() + + //In Hibernating Mode, the DP3T Module is not initialized and therefore the ENModuleVersion cannot be accessed + val enModuleVersion = try { + DP3T.getENModuleVersion(context).toString() + } catch (e: Exception) { + "" + } val configResponse = configService.getConfig(appVersion, osVersion, buildNumber, enModuleVersion) if (configResponse.isSuccessful) { secureStorage.lastConfigLoadSuccess = System.currentTimeMillis() diff --git a/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt b/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt index 1131eb22..15d6a26f 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt @@ -15,6 +15,7 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.os.Build +import android.util.Log import androidx.core.app.NotificationCompat import androidx.work.* import ch.admin.bag.dp3t.BuildConfig @@ -74,12 +75,16 @@ class ConfigWorker(context: Context, workerParams: WorkerParameters) : Coroutine val configRepository = ConfigRepository(context) val config = configRepository.getConfig(context) - DP3T.setMatchingParameters( - context, - config.sdkConfig.lowerThreshold, config.sdkConfig.higherThreshold, - config.sdkConfig.factorLow, config.sdkConfig.factorHigh, - config.sdkConfig.triggerThreshold - ) + try { + DP3T.setMatchingParameters( + context, + config.sdkConfig.lowerThreshold, config.sdkConfig.higherThreshold, + config.sdkConfig.factorLow, config.sdkConfig.factorHigh, + config.sdkConfig.triggerThreshold + ) + } catch (e: Exception) { + Log.d(TAG, "Matching paramters not set because DP3T is not initialized due to hibernating mode") + } val secureStorage = SecureStorage.getInstance(context) secureStorage.doForceUpdate = config.doForceUpdate @@ -127,7 +132,7 @@ class ConfigWorker(context: Context, workerParams: WorkerParameters) : Coroutine } private fun activateHibernationState(context: Context) { - DP3T.stop(context) + if (DP3T.isInitialized()) DP3T.stop(context) FakeWorker.stop(context) CrowdNotifierKeyLoadWorker.stop(context) NotificationRepeatWorker.stop(context) From e4d0f3972470c4fd024c1adf89cbe806ff00d90d Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Thu, 17 Mar 2022 17:32:22 +0100 Subject: [PATCH 13/14] Load Config after App Update and show Hibernation Fragment if necessary --- .../java/ch/admin/bag/dp3t/MainActivity.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt b/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt index ccd613e7..8da661f6 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt @@ -12,11 +12,13 @@ package ch.admin.bag.dp3t import android.content.* import android.net.Uri import android.os.Bundle +import android.util.Log import androidx.activity.result.ActivityResult import androidx.activity.viewModels import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity +import androidx.lifecycle.lifecycleScope import androidx.localbroadcastmanager.content.LocalBroadcastManager import ch.admin.bag.dp3t.checkin.CheckinOverviewFragment import ch.admin.bag.dp3t.checkin.CrowdNotifierViewModel @@ -31,6 +33,7 @@ import ch.admin.bag.dp3t.checkin.utils.ErrorDialog import ch.admin.bag.dp3t.checkin.utils.NotificationHelper import ch.admin.bag.dp3t.hibernate.HibernatingInfoFragment import ch.admin.bag.dp3t.inform.InformActivity +import ch.admin.bag.dp3t.networking.ConfigWorker import ch.admin.bag.dp3t.networking.ConfigWorker.Companion.scheduleConfigWorkerIfOutdated import ch.admin.bag.dp3t.onboarding.OnboardingActivityArgs import ch.admin.bag.dp3t.onboarding.OnboardingActivityResultContract @@ -44,6 +47,7 @@ import ch.admin.bag.dp3t.util.UrlUtil import ch.admin.bag.dp3t.viewmodel.TracingViewModel import ch.admin.bag.dp3t.whattodo.WtdPositiveTestFragment import com.google.android.gms.instantapps.InstantApps +import kotlinx.coroutines.launch import org.crowdnotifier.android.sdk.CrowdNotifier import org.crowdnotifier.android.sdk.utils.QrUtils.* import org.dpppt.android.sdk.DP3T @@ -88,6 +92,20 @@ class MainActivity : FragmentActivity() { } return } + + // After the App Update, load the config immediately to check whether hibernation mode is turned on + if (secureStorage.lastConfigLoadSuccessAppVersion != BuildConfig.VERSION_CODE) { + lifecycleScope.launch { + try { + ConfigWorker.loadConfig(this@MainActivity) + if (secureStorage.isHibernating) showHibernateFragment() + } catch (e: Exception) { + Log.d("MainActivity", "Failed to load Config after App Update") + } + + } + } + secureStorage.forceUpdateLiveData.observe(this) { val forceUpdate = it && secureStorage.doForceUpdate From 7e89d29d09ffe6b6d17aaf39b1f0eccac60c845c Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Fri, 18 Mar 2022 14:32:00 +0100 Subject: [PATCH 14/14] Fix language switch in hibernate fragment --- .../dp3t/hibernate/HibernatingInfoFragment.kt | 17 ++++++++++------- .../bag/dp3t/hibernate/HibernatingViewModel.kt | 9 +++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt index 623d7811..45820dd2 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt @@ -11,6 +11,7 @@ import ch.admin.bag.dp3t.R import ch.admin.bag.dp3t.TabbarHostFragment import ch.admin.bag.dp3t.databinding.FragmentHibernatingInfoBinding import ch.admin.bag.dp3t.html.HtmlFragment +import ch.admin.bag.dp3t.networking.models.InfoBoxModel import ch.admin.bag.dp3t.util.AssetUtil import ch.admin.bag.dp3t.util.UrlUtil @@ -37,13 +38,15 @@ class HibernatingInfoFragment : Fragment() { } } - viewModel.hibernatingInfoBox.observe(viewLifecycleOwner) { - title.text = it.title - text.text = it.msg - linkGroup.isVisible = it.urlTitle != null - linkText.text = it.urlTitle - linkGroup.setOnClickListener { v -> UrlUtil.openUrl(requireContext(), it.url) } - + viewModel.hibernatingInfoBox.observe(viewLifecycleOwner) { infoBoxModelCollection -> + val infobox = infoBoxModelCollection?.getInfoBox(getString(R.string.language_key)) + infobox?.let { + title.text = it.title + text.text = it.msg + linkGroup.isVisible = it.urlTitle != null + linkText.text = it.urlTitle + linkGroup.setOnClickListener { v -> UrlUtil.openUrl(requireContext(), it.url) } + } } }.root diff --git a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt index 3e036978..5263e9c8 100644 --- a/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt +++ b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt @@ -29,12 +29,9 @@ class HibernatingViewModel(application: Application) : AndroidViewModel(applicat val isHibernatingModeEnabled: LiveData = isHibernatingModeEnabledMutable private val secureStorage: SecureStorage by lazy { SecureStorage.getInstance(application) } - private val languageKey = application.getString(R.string.language_key) - - private val hibernatingInfoboxMutable = - MutableLiveData(secureStorage.hibernatingInfoboxCollection?.getInfoBox(languageKey)) - val hibernatingInfoBox: LiveData = hibernatingInfoboxMutable + private val hibernatingInfoboxMutable = MutableLiveData(secureStorage.hibernatingInfoboxCollection) + val hibernatingInfoBox: LiveData = hibernatingInfoboxMutable init { loadConfig() @@ -47,7 +44,7 @@ class HibernatingViewModel(application: Application) : AndroidViewModel(applicat ConfigWorker.loadConfig(getApplication()) if (secureStorage.isHibernating) { isHibernatingModeEnabledMutable.value = true - hibernatingInfoboxMutable.value = secureStorage.hibernatingInfoboxCollection?.getInfoBox(languageKey) + hibernatingInfoboxMutable.value = secureStorage.hibernatingInfoboxCollection } else { MainApplication.initDP3T(getApplication()) FakeWorker.safeStartFakeWorker(getApplication())