Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

Commit

Permalink
Merge pull request #916 from corona-warn-app/staging
Browse files Browse the repository at this point in the history
Release 1.2.0
  • Loading branch information
pwoessner committed Aug 6, 2020
2 parents b9ebc9c + 44f257b commit 137cfc9
Show file tree
Hide file tree
Showing 82 changed files with 6,515 additions and 1,062 deletions.
19 changes: 8 additions & 11 deletions Corona-Warn-App/build.gradle
Expand Up @@ -33,11 +33,12 @@ android {
applicationId 'de.rki.coronawarnapp'
minSdkVersion 23
targetSdkVersion 29
versionCode 34
versionName "1.1.1"
versionCode 35
versionName "1.2.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

resConfigs "de", "en", "tr"
resConfigs "de", "en", "tr", "bg", "pl", "ro"

buildConfigField "String", "DOWNLOAD_CDN_URL", "\"$DOWNLOAD_CDN_URL\""
buildConfigField "String", "SUBMISSION_CDN_URL", "\"$SUBMISSION_CDN_URL\""
Expand Down Expand Up @@ -124,13 +125,8 @@ android {
}

buildFeatures {
dataBinding {
enabled true
}

viewBinding {
enabled true
}
dataBinding true
viewBinding true
}

compileOptions {
Expand Down Expand Up @@ -247,6 +243,7 @@ dependencies {

// TESTING
testImplementation 'junit:junit:4.13'
testImplementation "android.arch.core:core-testing:1.1.1"
testImplementation "org.mockito:mockito-core:3.3.3"
testImplementation('org.robolectric:robolectric:4.3.1') {
exclude group: 'com.google.protobuf'
Expand All @@ -269,7 +266,7 @@ dependencies {
implementation 'com.google.android.gms:play-services-basement:17.3.0'
implementation 'com.google.android.gms:play-services-safetynet:17.0.0'
implementation 'com.google.android.gms:play-services-tasks:17.1.0'
api fileTree(dir: 'libs', include: ['play-services-nearby-18.0.2-eap.aar'])
api fileTree(dir: 'libs', include: ['play-services-nearby-18.0.3-eap.aar'])

// HTTP
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
Expand Down
Binary file not shown.
Binary file not shown.
Expand Up @@ -72,6 +72,7 @@ import kotlinx.android.synthetic.deviceForTesters.fragment_test_for_a_p_i.label_
import kotlinx.android.synthetic.deviceForTesters.fragment_test_for_a_p_i.label_my_keys
import kotlinx.android.synthetic.deviceForTesters.fragment_test_for_a_p_i.qr_code_viewpager
import kotlinx.android.synthetic.deviceForTesters.fragment_test_for_a_p_i.test_api_switch_last_three_hours_from_server
import kotlinx.android.synthetic.deviceForTesters.fragment_test_for_a_p_i.test_api_switch_background_notifications
import kotlinx.android.synthetic.deviceForTesters.fragment_test_for_a_p_i.text_my_keys
import kotlinx.android.synthetic.deviceForTesters.fragment_test_for_a_p_i.text_scanned_key
import kotlinx.coroutines.Dispatchers
Expand Down Expand Up @@ -181,6 +182,14 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
LocalData.last3HoursMode(isLast3HoursModeEnabled)
}

val backgroundNotificationSwitch = test_api_switch_background_notifications as Switch
backgroundNotificationSwitch.isChecked = LocalData.backgroundNotification()
backgroundNotificationSwitch.setOnClickListener {
val isBackgroundNotificationsActive = backgroundNotificationSwitch.isChecked
showToast("Background Notifications are activated: $isBackgroundNotificationsActive")
LocalData.backgroundNotification(isBackgroundNotificationsActive)
}

button_api_get_check_exposure.setOnClickListener {
checkExposure()
}
Expand Down
Expand Up @@ -189,7 +189,6 @@ class MainFragment : Fragment() {
// check if the dialog explaining the tracing time was already shown
if (!LocalData.tracingExplanationDialogWasShown()) {


val activity = this.requireActivity()

lifecycleScope.launch {
Expand Down
Expand Up @@ -96,9 +96,12 @@
style="@style/bodyButton"
android:layout_width="@dimen/match_constraint"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacing_small"
android:focusable="false"
android:text="@{FormatterSettingsHelper.formatTracingDescription(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
android:contentDescription="@{FormatterSettingsHelper.formatTracingContentDescription(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled(), settingsViewModel.isLocationEnabled())}"
android:text="@{FormatterSettingsHelper.formatTracingDescription(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled(), settingsViewModel.isLocationEnabled())}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/main_tracing_icon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

Expand All @@ -107,8 +110,8 @@
android:layout_width="@dimen/icon_size_main_card"
android:layout_height="@dimen/icon_size_main_card"
android:importantForAccessibility="no"
app:animation="@{FormatterSettingsHelper.formatTracingIcon(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
app:animation_tint="@{FormatterSettingsHelper.formatTracingIconColor(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
app:animation="@{FormatterSettingsHelper.formatTracingIcon(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled(), settingsViewModel.isLocationEnabled())}"
app:animation_tint="@{FormatterSettingsHelper.formatTracingIconColor(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled(), settingsViewModel.isLocationEnabled())}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Expand Down
Expand Up @@ -33,6 +33,14 @@
android:text="@string/test_api_switch_last_three_hours_from_server"
android:theme="@style/switchBase" />

<Switch
android:id="@+id/test_api_switch_background_notifications"
style="@style/body1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/test_api_switch_background_notifications"
android:theme="@style/switchBase" />

<TextView
android:id="@+id/label_exposure_summary"
style="@style/headline6"
Expand Down
8 changes: 8 additions & 0 deletions Corona-Warn-App/src/main/AndroidManifest.xml
Expand Up @@ -11,6 +11,7 @@
android:required="true" />
<uses-feature android:name="android.hardware.bluetooth" />

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission
android:name="android.permission.BLUETOOTH"
android:required="true" />
Expand All @@ -20,6 +21,8 @@

<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

<uses-permission android:name="android.permission.WAKE_LOCK" />

<application
android:name="de.rki.coronawarnapp.CoronaWarnApplication"
android:allowBackup="false"
Expand All @@ -30,6 +33,11 @@
android:supportsRtl="true"
android:theme="@style/AppTheme">

<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove" />

<receiver
android:name=".receiver.ExposureStateUpdateReceiver"
android:permission="com.google.android.gms.nearby.exposurenotification.EXPOSURE_CALLBACK">
Expand Down
8 changes: 0 additions & 8 deletions Corona-Warn-App/src/main/assets/technical_de.html
Expand Up @@ -6,14 +6,6 @@ <h2>Third Party Notices</h2>
to our attention by contacting us via this email:
corona-warn-app.opensource@sap.com</p>
<h2>Components:</h2>
<p>Component: JUnit 4
Licensor: The JUnit Team
Website: https://junit.org/junit4/
License: Eclipse Public License 1.0</p>
<p>Component: Java Hamcrest
Licensor: www.hamcrest.org
Website: https://github.com/hamcrest/JavaHamcrest
License: BSD-style license</p>
<p>Component: android-database-sqlcipher
Licensor: Zetetic LLC
Website: https://www.zetetic.net/sqlcipher/
Expand Down
8 changes: 0 additions & 8 deletions Corona-Warn-App/src/main/assets/technical_en.html
Expand Up @@ -6,14 +6,6 @@ <h2>Third Party Notices</h2>
to our attention by contacting us via this email:
corona-warn-app.opensource@sap.com</p>
<h2>Components:</h2>
<p>Component: JUnit 4
Licensor: The JUnit Team
Website: https://junit.org/junit4/
License: Eclipse Public License 1.0</p>
<p>Component: Java Hamcrest
Licensor: www.hamcrest.org
Website: https://github.com/hamcrest/JavaHamcrest
License: BSD-style license</p>
<p>Component: android-database-sqlcipher
Licensor: Zetetic LLC
Website: https://www.zetetic.net/sqlcipher/
Expand Down
8 changes: 0 additions & 8 deletions Corona-Warn-App/src/main/assets/technical_tr.html
Expand Up @@ -6,14 +6,6 @@ <h2>Third Party Notices</h2>
to our attention by contacting us via this email:
corona-warn-app.opensource@sap.com</p>
<h2>Components:</h2>
<p>Component: JUnit 4
Licensor: The JUnit Team
Website: https://junit.org/junit4/
License: Eclipse Public License 1.0</p>
<p>Component: Java Hamcrest
Licensor: www.hamcrest.org
Website: https://github.com/hamcrest/JavaHamcrest
License: BSD-style license</p>
<p>Component: android-database-sqlcipher
Licensor: Zetetic LLC
Website: https://www.zetetic.net/sqlcipher/
Expand Down
2 changes: 1 addition & 1 deletion Corona-Warn-App/src/main/assets/terms_de.html
Expand Up @@ -464,7 +464,7 @@
</p>
<p>
Eine ausführliche Anleitung zur Einrichtung der App unter iOS und Android
finden Sie unter [<em>Link</em>]. Die Anleitung dient lediglich der
finden Sie unter https://www.coronawarn.app/de/. Die Anleitung dient lediglich der
Erläuterung und ist nicht Teil dieser Nutzungsbedingungen.
</p>
<p>
Expand Down
2 changes: 1 addition & 1 deletion Corona-Warn-App/src/main/assets/terms_tr.html
Expand Up @@ -441,7 +441,7 @@
</p>
<p>
iOS ve Android uyarınca UYGULAMA'nın ayarlanması ile ilgili ayrıntılı
talimatı [<em>Link</em>] bulabilirsiniz. Kılavuz sadece aydınlatma amacı
talimatı https://www.coronawarn.app/en/ bulabilirsiniz. Kılavuz sadece aydınlatma amacı
taşır ve bu kullanım koşullarının bir parçası değildir.
</p>
<p>
Expand Down
Expand Up @@ -6,19 +6,30 @@ import android.app.Application
import android.content.Context
import android.content.IntentFilter
import android.content.pm.ActivityInfo
import android.net.wifi.WifiManager
import android.os.Bundle
import android.view.WindowManager
import android.os.PowerManager
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.work.Configuration
import androidx.work.WorkManager
import de.rki.coronawarnapp.exception.reporting.ErrorReportReceiver
import de.rki.coronawarnapp.exception.reporting.ReportingConstants.ERROR_REPORT_LOCAL_BROADCAST_CHANNEL
import de.rki.coronawarnapp.notification.NotificationHelper
import de.rki.coronawarnapp.storage.LocalData
import de.rki.coronawarnapp.transaction.RetrieveDiagnosisKeysTransaction
import de.rki.coronawarnapp.util.ConnectivityHelper
import de.rki.coronawarnapp.worker.BackgroundWorkHelper
import de.rki.coronawarnapp.worker.BackgroundWorkScheduler
import kotlinx.coroutines.launch
import org.conscrypt.Conscrypt
import timber.log.Timber
import java.security.Security
import java.util.UUID

class CoronaWarnApplication : Application(), LifecycleObserver,
Application.ActivityLifecycleCallbacks {
Expand All @@ -36,13 +47,21 @@ class CoronaWarnApplication : Application(), LifecycleObserver,

fun getAppContext(): Context =
instance.applicationContext

const val TEN_MINUTE_TIMEOUT_IN_MS = 10 * 60 * 1000L
}

private lateinit var errorReceiver: ErrorReportReceiver

override fun onCreate() {
super.onCreate()
instance = this

val configuration = Configuration.Builder()
.setMinimumLoggingLevel(android.util.Log.DEBUG)
.build()
WorkManager.initialize(this, configuration)

NotificationHelper.createNotificationChannel()
// Enable Conscrypt for TLS1.3 Support below API Level 29
Security.insertProviderAt(Conscrypt.newProvider(), 1)
Expand All @@ -52,6 +71,62 @@ class CoronaWarnApplication : Application(), LifecycleObserver,
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}

// notification to test the WakeUpService from Google when the app
// was force stopped
BackgroundWorkHelper.sendDebugNotification(
"Application onCreate", "App was woken up"
)
// Only do this if the background jobs are enabled
if (ConnectivityHelper.autoModeEnabled(applicationContext)) {
ProcessLifecycleOwner.get().lifecycleScope.launch {
// we want a wakelock as the OS does not handle this for us like in the background
// job execution
val wakeLock: PowerManager.WakeLock =
(getSystemService(Context.POWER_SERVICE) as PowerManager).run {
newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
TAG + "-WAKE-" + UUID.randomUUID().toString()
).apply {
acquire(TEN_MINUTE_TIMEOUT_IN_MS)
}
}

// we keep a wifi lock to wake up the wifi connection in case the device is dozing
val wifiLock: WifiManager.WifiLock =
(getSystemService(Context.WIFI_SERVICE) as WifiManager).run {
createWifiLock(
WifiManager.WIFI_MODE_FULL_HIGH_PERF,
TAG + "-WIFI-" + UUID.randomUUID().toString()
).apply {
acquire()
}
}

try {
BackgroundWorkHelper.sendDebugNotification(
"Automatic mode is on", "Check if we have downloaded keys already today"
)
RetrieveDiagnosisKeysTransaction.startWithConstraints()
} catch (e: Exception) {
BackgroundWorkHelper.sendDebugNotification(
"RetrieveDiagnosisKeysTransaction failed",
(e.localizedMessage
?: "Unknown exception occurred in onCreate") + "\n\n" + (e.cause
?: "Cause is unknown").toString()
)
// retry the key retrieval in case of an error with a scheduled work
BackgroundWorkScheduler.scheduleDiagnosisKeyOneTimeWork()
}

if (wifiLock.isHeld) wifiLock.release()
if (wakeLock.isHeld) wakeLock.release()
}

// if the user is onboarded we will schedule period background jobs
// in case the app was force stopped and woken up again by the Google WakeUpService
if (LocalData.onboardingCompletedTimestamp() != null) BackgroundWorkScheduler.startWorkScheduler()
}
}

/**
Expand Down Expand Up @@ -95,15 +170,6 @@ class CoronaWarnApplication : Application(), LifecycleObserver,

@SuppressLint("SourceLockedOrientationActivity")
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
// prevents screenshot of the app for all activities,
// except for deviceForTesters build flavor, which is used for testing
if (BuildConfig.FLAVOR != "deviceForTesters") {
activity.window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
}

// set screen orientation to portrait
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
}
Expand Down
Expand Up @@ -6,7 +6,9 @@ import com.google.android.gms.common.api.ApiException
import de.rki.coronawarnapp.CoronaWarnApplication
import de.rki.coronawarnapp.R
import de.rki.coronawarnapp.exception.ExceptionCategory
import de.rki.coronawarnapp.exception.reporting.ReportingConstants.STATUS_CODE_GOOGLE_API_FAIL
import de.rki.coronawarnapp.exception.reporting.ReportingConstants.STATUS_CODE_GOOGLE_UPDATE_NEEDED
import de.rki.coronawarnapp.exception.reporting.ReportingConstants.STATUS_CODE_REACHED_REQUEST_LIMIT
import java.io.PrintWriter
import java.io.StringWriter

Expand Down Expand Up @@ -38,6 +40,10 @@ fun Throwable.report(

if (this.statusCode == STATUS_CODE_GOOGLE_UPDATE_NEEDED) {
errorMessage = R.string.errors_google_update_needed
} else if (this.statusCode == STATUS_CODE_REACHED_REQUEST_LIMIT ||
this.statusCode == STATUS_CODE_GOOGLE_API_FAIL
) {
errorMessage = R.string.errors_google_api_error
}

intent.putExtra(
Expand Down
Expand Up @@ -13,4 +13,6 @@ object ReportingConstants {
val ERROR_REPORT_UNKNOWN_ERROR = ErrorCodes.REPORTED_EXCEPTION_UNKNOWN_PROBLEM.code

const val STATUS_CODE_GOOGLE_UPDATE_NEEDED = 17
const val STATUS_CODE_REACHED_REQUEST_LIMIT = 39508
const val STATUS_CODE_GOOGLE_API_FAIL = 10
}

0 comments on commit 137cfc9

Please sign in to comment.