Skip to content
Snippets Groups Projects
Unverified Commit 0d90fad8 authored by Philipp Woessner's avatar Philipp Woessner Committed by GitHub
Browse files

Improved test fragments for risk level calculation (#205)


* added text style for 3 hour mode

* possibility to see all key qr codes, added risk level reset, set transmission risk level for risk level calc

Co-authored-by: default avatarJakob Möller <jakob.moeller@sap.com>
parent cd4660e8
No related branches found
No related tags found
No related merge requests found
...@@ -2,11 +2,14 @@ package de.rki.coronawarnapp ...@@ -2,11 +2,14 @@ package de.rki.coronawarnapp
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.util.Base64
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView
import android.widget.Switch import android.widget.Switch
import android.widget.Toast import android.widget.Toast
import androidx.core.content.pm.PackageInfoCompat import androidx.core.content.pm.PackageInfoCompat
...@@ -14,6 +17,8 @@ import androidx.fragment.app.Fragment ...@@ -14,6 +17,8 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.google.android.gms.common.GoogleApiAvailability import com.google.android.gms.common.GoogleApiAvailability
import com.google.android.gms.nearby.exposurenotification.ExposureConfiguration import com.google.android.gms.nearby.exposurenotification.ExposureConfiguration
import com.google.android.gms.nearby.exposurenotification.ExposureNotificationClient import com.google.android.gms.nearby.exposurenotification.ExposureNotificationClient
...@@ -21,8 +26,11 @@ import com.google.android.gms.nearby.exposurenotification.ExposureSummary ...@@ -21,8 +26,11 @@ import com.google.android.gms.nearby.exposurenotification.ExposureSummary
import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import com.google.protobuf.ByteString
import com.google.zxing.BarcodeFormat
import com.google.zxing.integration.android.IntentIntegrator import com.google.zxing.integration.android.IntentIntegrator
import com.google.zxing.integration.android.IntentResult import com.google.zxing.integration.android.IntentResult
import com.google.zxing.qrcode.QRCodeWriter
import de.rki.coronawarnapp.databinding.FragmentTestForAPIBinding import de.rki.coronawarnapp.databinding.FragmentTestForAPIBinding
import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.ExceptionCategory
import de.rki.coronawarnapp.exception.ExceptionCategory.INTERNAL import de.rki.coronawarnapp.exception.ExceptionCategory.INTERNAL
...@@ -56,7 +64,6 @@ import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.button_insert_expo ...@@ -56,7 +64,6 @@ import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.button_insert_expo
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.button_retrieve_exposure_summary import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.button_retrieve_exposure_summary
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.button_tracing_duration_in_retention_period import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.button_tracing_duration_in_retention_period
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.button_tracing_intervals import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.button_tracing_intervals
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.image_qr_code
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_exposure_summary_attenuation import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_exposure_summary_attenuation
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_exposure_summary_daysSinceLastExposure import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_exposure_summary_daysSinceLastExposure
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_exposure_summary_matchedKeyCount import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_exposure_summary_matchedKeyCount
...@@ -64,6 +71,7 @@ import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_exposure_sum ...@@ -64,6 +71,7 @@ import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_exposure_sum
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_exposure_summary_summationRiskScore import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_exposure_summary_summationRiskScore
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_googlePlayServices_version import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_googlePlayServices_version
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_my_keys import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.label_my_keys
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.qr_code_viewpager
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.test_api_switch_last_three_hours_from_server import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.test_api_switch_last_three_hours_from_server
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.text_my_keys import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.text_my_keys
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.text_scanned_key import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.text_scanned_key
...@@ -93,6 +101,7 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel ...@@ -93,6 +101,7 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
} }
private var myExposureKeysJSON: String? = null private var myExposureKeysJSON: String? = null
private var myExposureKeys: List<TemporaryExposureKey>? = mutableListOf()
private var otherExposureKey: AppleLegacyKeyExchange.Key? = null private var otherExposureKey: AppleLegacyKeyExchange.Key? = null
private var otherExposureKeyList = mutableListOf<AppleLegacyKeyExchange.Key>() private var otherExposureKeyList = mutableListOf<AppleLegacyKeyExchange.Key>()
...@@ -103,6 +112,9 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel ...@@ -103,6 +112,9 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
// ViewModel for MainActivity // ViewModel for MainActivity
private val tracingViewModel: TracingViewModel by activityViewModels() private val tracingViewModel: TracingViewModel by activityViewModels()
private lateinit var qrPager: ViewPager2
private lateinit var qrPagerAdapter: RecyclerView.Adapter<QRPagerAdapter.QRViewHolder>
// Data and View binding // Data and View binding
private var _binding: FragmentTestForAPIBinding? = null private var _binding: FragmentTestForAPIBinding? = null
private val binding: FragmentTestForAPIBinding get() = _binding!! private val binding: FragmentTestForAPIBinding get() = _binding!!
...@@ -147,15 +159,16 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel ...@@ -147,15 +159,16 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
internalExposureNotificationPermissionHelper = internalExposureNotificationPermissionHelper =
InternalExposureNotificationPermissionHelper(this, this) InternalExposureNotificationPermissionHelper(this, this)
qrPager = qr_code_viewpager
qrPagerAdapter = QRPagerAdapter()
qrPager.adapter = qrPagerAdapter
button_api_test_start.setOnClickListener { button_api_test_start.setOnClickListener {
start() start()
} }
button_api_get_exposure_keys.setOnClickListener { button_api_get_exposure_keys.setOnClickListener {
getExposureKeys() getExposureKeys()
tracingViewModel.viewModelScope.launch {
ExposureSharingService.shareKeysAsBitmap(300, 300, updateQRImageView)
}
} }
val last3HoursSwitch = test_api_switch_last_three_hours_from_server as Switch val last3HoursSwitch = test_api_switch_last_three_hours_from_server as Switch
...@@ -257,13 +270,6 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel ...@@ -257,13 +270,6 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
getExposureKeys() getExposureKeys()
} }
private val updateQRImageView = { bitmap: Bitmap? ->
bitmap?.let {
image_qr_code.setImageBitmap(bitmap)
image_qr_code.visibility = View.VISIBLE
}
}
private val prettyKey = { key: AppleLegacyKeyExchange.Key -> private val prettyKey = { key: AppleLegacyKeyExchange.Key ->
StringBuilder() StringBuilder()
.append("\nKey data: ${key.keyData}") .append("\nKey data: ${key.keyData}")
...@@ -439,10 +445,6 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel ...@@ -439,10 +445,6 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
) )
label_my_keys.text = myKeysLabelAndCount label_my_keys.text = myKeysLabelAndCount
text_my_keys.text = myExposureKeysJSON text_my_keys.text = myExposureKeysJSON
tracingViewModel.viewModelScope.launch {
ExposureSharingService.shareKeysAsBitmap(300, 300, updateQRImageView)
}
} }
private fun showToast(message: String) { private fun showToast(message: String) {
...@@ -461,6 +463,9 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel ...@@ -461,6 +463,9 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
override fun onKeySharePermissionGranted(keys: List<TemporaryExposureKey>) { override fun onKeySharePermissionGranted(keys: List<TemporaryExposureKey>) {
myExposureKeysJSON = myExposureKeysJSON =
keysToJson(keys) keysToJson(keys)
myExposureKeys = keys
qrPagerAdapter.notifyDataSetChanged()
updateKeysDisplay() updateKeysDisplay()
} }
...@@ -507,4 +512,46 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel ...@@ -507,4 +512,46 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
CONFIG_SCORE CONFIG_SCORE
) )
.build() .build()
private inner class QRPagerAdapter :
RecyclerView.Adapter<QRPagerAdapter.QRViewHolder>() {
inner class QRViewHolder(val qrCode: ImageView) : RecyclerView.ViewHolder(qrCode)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QRViewHolder {
val imageView = LayoutInflater.from(parent.context)
.inflate(R.layout.test_qr_code_view, parent, false) as ImageView
return QRViewHolder(imageView)
}
override fun getItemCount(): Int = myExposureKeys?.size ?: 0
override fun onBindViewHolder(holder: QRViewHolder, position: Int) {
myExposureKeys?.get(position)?.let {
holder.qrCode.setImageBitmap(bitmapForImage(it))
}
}
private fun bitmapForImage(key: TemporaryExposureKey): Bitmap {
val key = AppleLegacyKeyExchange.Key.newBuilder()
.setKeyData(ByteString.copyFrom(key.keyData))
.setRollingPeriod(key.rollingPeriod)
.setRollingStartNumber(key.rollingStartIntervalNumber)
.build().toByteArray()
val bMatrix = QRCodeWriter().encode(
Base64.encodeToString(key, Base64.DEFAULT),
BarcodeFormat.QR_CODE,
300,
300
)
val bmp =
Bitmap.createBitmap(bMatrix.width, bMatrix.height, Bitmap.Config.RGB_565)
for (x in 0 until bMatrix.width) {
for (y in 0 until bMatrix.height) {
bmp.setPixel(x, y, if (bMatrix.get(x, y)) Color.BLACK else Color.WHITE)
}
}
return bmp
}
}
} }
...@@ -6,6 +6,7 @@ import android.util.Log ...@@ -6,6 +6,7 @@ import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.EditText
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
...@@ -26,6 +27,8 @@ import de.rki.coronawarnapp.server.protocols.AppleLegacyKeyExchange ...@@ -26,6 +27,8 @@ import de.rki.coronawarnapp.server.protocols.AppleLegacyKeyExchange
import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass
import de.rki.coronawarnapp.service.applicationconfiguration.ApplicationConfigurationService import de.rki.coronawarnapp.service.applicationconfiguration.ApplicationConfigurationService
import de.rki.coronawarnapp.sharing.ExposureSharingService import de.rki.coronawarnapp.sharing.ExposureSharingService
import de.rki.coronawarnapp.storage.AppDatabase
import de.rki.coronawarnapp.storage.FileStorageHelper
import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.LocalData
import de.rki.coronawarnapp.transaction.RetrieveDiagnosisKeysTransaction import de.rki.coronawarnapp.transaction.RetrieveDiagnosisKeysTransaction
import de.rki.coronawarnapp.transaction.RiskLevelTransaction import de.rki.coronawarnapp.transaction.RiskLevelTransaction
...@@ -33,7 +36,10 @@ import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel ...@@ -33,7 +36,10 @@ import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel
import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel
import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel
import de.rki.coronawarnapp.util.KeyFileHelper import de.rki.coronawarnapp.util.KeyFileHelper
import kotlinx.android.synthetic.main.fragment_test_risk_level_calculation.transmission_number
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File import java.io.File
import java.util.UUID import java.util.UUID
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
...@@ -94,6 +100,33 @@ class TestRiskLevelCalculation : Fragment() { ...@@ -94,6 +100,33 @@ class TestRiskLevelCalculation : Fragment() {
} }
} }
binding.buttonResetRiskLevel.setOnClickListener {
tracingViewModel.viewModelScope.launch {
withContext(Dispatchers.IO) {
try {
// Database Reset
AppDatabase.getInstance(requireContext()).clearAllTables()
// Delete Database Instance
AppDatabase.resetInstance(requireContext())
// Export File Reset
FileStorageHelper.getAllFilesInKeyExportDirectory().forEach { it.delete() }
LocalData.lastCalculatedRiskLevel(RiskLevel.UNDETERMINED.raw)
LocalData.lastSuccessfullyCalculatedRiskLevel(RiskLevel.UNDETERMINED.raw)
LocalData.lastTimeDiagnosisKeysFromServerFetch(null)
LocalData.googleApiToken(null)
} catch (e: java.lang.Exception) {
e.report(ExceptionCategory.INTERNAL)
}
}
RiskLevelTransaction.start()
Toast.makeText(
requireContext(), "Resetted, please fetch diagnosis keys from server again",
Toast.LENGTH_SHORT
).show()
}
}
startObserving() startObserving()
} }
...@@ -151,12 +184,18 @@ class TestRiskLevelCalculation : Fragment() { ...@@ -151,12 +184,18 @@ class TestRiskLevelCalculation : Fragment() {
val appleKeyList = mutableListOf<AppleLegacyKeyExchange.Key>() val appleKeyList = mutableListOf<AppleLegacyKeyExchange.Key>()
val text = (transmission_number as EditText).text.toString()
var number = 5
if (!text.isBlank()) {
number = Integer.valueOf(text)
}
appleKeyList.add( appleKeyList.add(
AppleLegacyKeyExchange.Key.newBuilder() AppleLegacyKeyExchange.Key.newBuilder()
.setKeyData(key.keyData) .setKeyData(key.keyData)
.setRollingPeriod(144) .setRollingPeriod(144)
.setRollingStartNumber(key.rollingStartNumber) .setRollingStartNumber(key.rollingStartNumber)
.setTransmissionRiskLevel(1) .setTransmissionRiskLevel(number)
.build() .build()
) )
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <layout xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:app="http://schemas.android.com/apk/res-auto">
<data> <data>
...@@ -111,11 +110,10 @@ ...@@ -111,11 +110,10 @@
android:lines="5" android:lines="5"
android:visibility="gone" /> android:visibility="gone" />
<ImageView <androidx.viewpager2.widget.ViewPager2
android:id="@+id/image_qr_code" android:id="@+id/qr_code_viewpager"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="200dp" android:layout_height="200dp" />
app:srcCompat="@drawable/button" />
<TextView <TextView
android:id="@+id/label_other_keys" android:id="@+id/label_other_keys"
......
...@@ -49,6 +49,34 @@ ...@@ -49,6 +49,34 @@
app:showDetails="@{false}" app:showDetails="@{false}"
app:tracingViewModel="@{tracingViewModel}" /> app:tracingViewModel="@{tracingViewModel}" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_normal"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Transmission Risk Level for scan: " />
<EditText
android:id="@+id/transmission_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number"
android:text="5" />
</LinearLayout>
<Button
android:id="@+id/button_provide_key_via_qr"
style="@style/buttonPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/spacing_normal"
android:text="Scan Local QR Code" />
<Button <Button
android:id="@+id/button_retrieve_diagnosis_keys" android:id="@+id/button_retrieve_diagnosis_keys"
style="@style/buttonPrimary" style="@style/buttonPrimary"
...@@ -58,20 +86,20 @@ ...@@ -58,20 +86,20 @@
android:text="Retrieve Diagnosis Keys" /> android:text="Retrieve Diagnosis Keys" />
<Button <Button
android:id="@+id/button_provide_key_via_qr" android:id="@+id/button_calculate_risk_level"
style="@style/buttonPrimary" style="@style/buttonPrimary"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_normal" android:layout_marginTop="@dimen/spacing_normal"
android:text="Scan Local QR Code" /> android:text="Calculate Risk Level" />
<Button <Button
android:id="@+id/button_calculate_risk_level" android:id="@+id/button_reset_risk_level"
style="@style/buttonPrimary" style="@style/buttonPrimary"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_normal" android:layout_marginTop="@dimen/spacing_normal"
android:text="Calculate Risk Level" /> android:text="Reset Risk Level" />
<TextView <TextView
android:id="@+id/label_exposure_summary_title" android:id="@+id/label_exposure_summary_title"
......
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/image_qr_code"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:srcCompat="@drawable/button" />
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment