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' 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..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 @@ -29,7 +31,9 @@ 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 import ch.admin.bag.dp3t.networking.ConfigWorker.Companion.scheduleConfigWorkerIfOutdated import ch.admin.bag.dp3t.onboarding.OnboardingActivityArgs import ch.admin.bag.dp3t.onboarding.OnboardingActivityResultContract @@ -43,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 @@ -62,7 +67,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() @@ -78,7 +85,28 @@ class MainActivity : FragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - secureStorage.forceUpdateLiveData.observe(this, { + val isInHibernatingState = secureStorage.isHibernating + if (isInHibernatingState) { + if (savedInstanceState == null) { + showHibernateFragment() + } + 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 @@ -96,7 +124,7 @@ class MainActivity : FragmentActivity() { } forceUpdateDialog.show() } - }) + } scheduleConfigWorkerIfOutdated(this) CrowdNotifierKeyLoadWorker.startKeyLoadWorker(this) CrowdNotifierKeyLoadWorker.cleanUpOldData(this) @@ -111,7 +139,6 @@ class MainActivity : FragmentActivity() { lastShownUpdateBoardingVersion < UPDATE_BOARDING_VERSION -> OnboardingType.UPDATE_BOARDING else -> null } - if (onboardingType == null) { showHomeFragment() } else { @@ -174,7 +201,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)) } @@ -285,6 +312,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/MainApplication.java b/app/src/main/java/ch/admin/bag/dp3t/MainApplication.java index 0558a024..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); 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/hibernate/HibernatingInfoFragment.kt b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt new file mode 100644 index 00000000..45820dd2 --- /dev/null +++ b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingInfoFragment.kt @@ -0,0 +1,78 @@ +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 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.networking.models.InfoBoxModel +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 viewModel: HibernatingViewModel by viewModels() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return FragmentHibernatingInfoBinding.inflate(inflater).apply { + + toolbar.setOnMenuItemClickListener { + showImpressum() + true + } + + viewModel.isHibernatingModeEnabled.observe(viewLifecycleOwner) { isHibernatingModeEnabled -> + if (!isHibernatingModeEnabled) { + showHomeFragment() + } + } + + 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 + } + + 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), + 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/hibernate/HibernatingViewModel.kt b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt new file mode 100644 index 00000000..5263e9c8 --- /dev/null +++ b/app/src/main/java/ch/admin/bag/dp3t/hibernate/HibernatingViewModel.kt @@ -0,0 +1,61 @@ +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.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 +import org.dpppt.android.sdk.DP3T +import org.dpppt.android.sdk.internal.logger.Logger + +class HibernatingViewModel(application: Application) : AndroidViewModel(application) { + + companion object { + private val TAG = "HibernatingViewModel" + + } + + private val isHibernatingModeEnabledMutable = MutableLiveData() + val isHibernatingModeEnabled: LiveData = isHibernatingModeEnabledMutable + + private val secureStorage: SecureStorage by lazy { SecureStorage.getInstance(application) } + + private val hibernatingInfoboxMutable = MutableLiveData(secureStorage.hibernatingInfoboxCollection) + val hibernatingInfoBox: LiveData = hibernatingInfoboxMutable + + init { + loadConfig() + } + + + private fun loadConfig() { + viewModelScope.launch { + try { + ConfigWorker.loadConfig(getApplication()) + if (secureStorage.isHibernating) { + isHibernatingModeEnabledMutable.value = true + hibernatingInfoboxMutable.value = secureStorage.hibernatingInfoboxCollection + } else { + MainApplication.initDP3T(getApplication()) + 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/CertificatePinning.java b/app/src/main/java/ch/admin/bag/dp3t/networking/CertificatePinning.java index 25b43405..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/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", 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(); 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 f4252f8f..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,15 +15,18 @@ 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 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,20 +66,29 @@ 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) { + suspend fun loadConfig(context: Context) { 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 + secureStorage.setWhatToDoPositiveTestTexts(config.whatToDoPositiveTestTexts) if (config.infoBox != null) { @@ -111,6 +123,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) { + if (DP3T.isInitialized()) 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/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/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) 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/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); } 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..d1198551 --- /dev/null +++ b/app/src/main/res/layout/fragment_hibernating_info.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/common/src/main/res/values-bs/strings.xml b/common/src/main/res/values-bs/strings.xml index 8b5322e6..2b3dbf20 100644 --- a/common/src/main/res/values-bs/strings.xml +++ b/common/src/main/res/values-bs/strings.xml @@ -1985,4 +1985,27 @@ Mnoga mesta nude i vakcinaciju bez zakazanog termina" "https://covid19.impf-check.ch/" "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-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..1ca3ce25 100644 --- a/common/src/main/res/values-es/strings.xml +++ b/common/src/main/res/values-es/strings.xml @@ -1978,4 +1978,27 @@ Muchos centros ofrecen la posibllidad de vacunarse sin cita previa." "https://covid19.impf-check.ch/" "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 3943c318..5a13cd0e 100644 --- a/common/src/main/res/values-fr/strings.xml +++ b/common/src/main/res/values-fr/strings.xml @@ -2009,4 +2009,27 @@ 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" + + + "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 f7fde2c5..4b80905a 100644 --- a/common/src/main/res/values-hr/strings.xml +++ b/common/src/main/res/values-hr/strings.xml @@ -1983,4 +1983,27 @@ Mnoga mesta nude i vakcinaciju bez zakazanog termina" "https://covid19.impf-check.ch/" "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 c4912a3d..1f43dd25 100644 --- a/common/src/main/res/values-it/strings.xml +++ b/common/src/main/res/values-it/strings.xml @@ -2018,4 +2018,27 @@ Molti di essi offrono anche vaccinazioni libere senza appuntamento." "https://covid19-vac-check.ch/" "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 10041c1b..4a9c6971 100644 --- a/common/src/main/res/values-pt/strings.xml +++ b/common/src/main/res/values-pt/strings.xml @@ -1987,4 +1987,27 @@ Muitos lugares também oferecem vacinações Walk-in sem agendamento." "https://covid19.impf-check.ch/" "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 481f2abf..86259bd6 100644 --- a/common/src/main/res/values-rm/strings.xml +++ b/common/src/main/res/values-rm/strings.xml @@ -1984,4 +1984,27 @@ Blers lieus porschan er vaccinaziuns «walk-in» senza termin." "https://covid19.impf-check.ch/" "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 70e0013d..1e3f5520 100644 --- a/common/src/main/res/values-sq/strings.xml +++ b/common/src/main/res/values-sq/strings.xml @@ -1989,4 +1989,27 @@ Shumë vende gjithashtu ofrojnë vaksinime pa takim." "https://covid19.impf-check.ch/" "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 d9088faf..c584372e 100644 --- a/common/src/main/res/values-sr/strings.xml +++ b/common/src/main/res/values-sr/strings.xml @@ -1983,4 +1983,27 @@ Mnoga mesta nude i vakcinaciju bez zakazanog termina" "https://covid19.impf-check.ch/" "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 cc06335d..6c42d57f 100644 --- a/common/src/main/res/values-ti/strings.xml +++ b/common/src/main/res/values-ti/strings.xml @@ -1970,4 +1970,27 @@ SwissCovid ነቶም ኣብቶም ተቓደውቲ ሃገራት ዝተዘርገ "https://covid19.impf-check.ch/" "ሕጂ ቘጸራ ሓዝ" + + + "ሓበሬታ" + + + "ኣሰራርሓ እቲ 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 347a72f3..df33778c 100644 --- a/common/src/main/res/values-tr/strings.xml +++ b/common/src/main/res/values-tr/strings.xml @@ -1970,4 +1970,27 @@ Birçok yerde, randevu almadan doğrudan aşı yaptırılabilmektedir." "https://covid19.impf-check.ch/" "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 a8152a7d..ea80ba0e 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -2009,4 +2009,27 @@ Many places also offer walk-in vaccinations without an appointment." "https://covid19.impf-check.ch/" "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