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 #179 from corona-warn-app/dev
Browse files Browse the repository at this point in the history
0.8.3
  • Loading branch information
jakobmoellerdev authored Jun 5, 2020
2 parents 00513d1 + 3bfeb0b commit 6d33c5b
Show file tree
Hide file tree
Showing 155 changed files with 7,607 additions and 4,270 deletions.
12 changes: 10 additions & 2 deletions Corona-Warn-App/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,23 @@ android {
applicationId 'de.rki.coronawarnapp'
minSdkVersion 23
targetSdkVersion 29
versionCode 9
versionName "0.8.2"
versionCode 10
versionName "0.8.3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

buildConfigField "String", "DOWNLOAD_CDN_URL", "\"$DOWNLOAD_CDN_URL\""
buildConfigField "String", "SUBMISSION_CDN_URL", "\"$SUBMISSION_CDN_URL\""
buildConfigField "String", "VERIFICATION_CDN_URL", "\"$VERIFICATION_CDN_URL\""
buildConfigField "String", "TRUSTED_CERTS_EXPORT_KEYSTORE_PW", "\"$TRUSTED_CERTS_EXPORT_KEYSTORE_PW\""

//override URLs with local variables
Properties properties = new Properties()
def propertiesFile = project.rootProject.file('local.properties')
if (propertiesFile.exists()) {
properties.load(propertiesFile.newDataInputStream())
def secretFile = project.rootProject.file('secrets.properties')
if (secretFile.exists())
properties.load(secretFile.newDataInputStream())

def DOWNLOAD_CDN_URL = properties.getProperty('DOWNLOAD_CDN_URL')
if (DOWNLOAD_CDN_URL)
Expand All @@ -58,6 +62,10 @@ android {
def VERIFICATION_CDN_URL = properties.getProperty('VERIFICATION_CDN_URL')
if (VERIFICATION_CDN_URL)
buildConfigField "String", "VERIFICATION_CDN_URL", "\"$VERIFICATION_CDN_URL\""

def TRUSTED_CERTS_EXPORT_KEYSTORE_PW = properties.getProperty('TRUSTED_CERTS_EXPORT_KEYSTORE_PW')
if (TRUSTED_CERTS_EXPORT_KEYSTORE_PW)
buildConfigField "String", "TRUSTED_CERTS_EXPORT_KEYSTORE_PW", "\"$TRUSTED_CERTS_EXPORT_KEYSTORE_PW\""
}
}

Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application
import android.content.Context
import android.content.IntentFilter
import android.content.pm.ActivityInfo
import android.os.Bundle
import android.util.Log
Expand All @@ -12,6 +13,10 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import de.rki.coronawarnapp.exception.ErrorReportReceiver
import de.rki.coronawarnapp.exception.ReportingConstants.ERROR_REPORT_LOCAL_BROADCAST_CHANNEL
import de.rki.coronawarnapp.exception.handler.GlobalExceptionHandler
import de.rki.coronawarnapp.notification.NotificationHelper
import org.conscrypt.Conscrypt
import java.security.Security
Expand All @@ -34,12 +39,15 @@ class CoronaWarnApplication : Application(), LifecycleObserver,
instance.applicationContext
}

private lateinit var errorReceiver: ErrorReportReceiver

override fun onCreate() {
super.onCreate()
GlobalExceptionHandler(this)
instance = this
NotificationHelper.createNotificationChannel()
// Enable Conscrypt for TLS1.3 Support below API Level 29
Security.insertProviderAt(Conscrypt.newProvider(), 1)
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
registerActivityLifecycleCallbacks(this)
}
Expand All @@ -63,7 +71,8 @@ class CoronaWarnApplication : Application(), LifecycleObserver,
}

override fun onActivityPaused(activity: Activity) {
// does not override function. Empty on intention
// unregisters error receiver
LocalBroadcastManager.getInstance(this).unregisterReceiver(errorReceiver)
}

override fun onActivityStarted(activity: Activity) {
Expand Down Expand Up @@ -94,6 +103,8 @@ class CoronaWarnApplication : Application(), LifecycleObserver,
}

override fun onActivityResumed(activity: Activity) {
// does not override function. Empty on intention
errorReceiver = ErrorReportReceiver(activity)
LocalBroadcastManager.getInstance(this)
.registerReceiver(errorReceiver, IntentFilter(ERROR_REPORT_LOCAL_BROADCAST_CHANNEL))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,35 @@ package de.rki.coronawarnapp

import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Color
import android.os.Bundle
import android.util.Base64
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.Switch
import android.widget.Toast
import androidx.core.content.pm.PackageInfoCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
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.nearby.exposurenotification.ExposureConfiguration
import com.google.android.gms.nearby.exposurenotification.ExposureNotificationClient
import com.google.android.gms.nearby.exposurenotification.ExposureSummary
import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
import com.google.gson.Gson
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.IntentResult
import com.google.zxing.qrcode.QRCodeWriter
import de.rki.coronawarnapp.databinding.FragmentTestForAPIBinding
import de.rki.coronawarnapp.exception.ExceptionCategory
import de.rki.coronawarnapp.exception.ExceptionCategory.INTERNAL
Expand Down Expand Up @@ -55,14 +64,15 @@ 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_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.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_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_maximumRiskScore
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_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.text_my_keys
import kotlinx.android.synthetic.main.fragment_test_for_a_p_i.text_scanned_key
import kotlinx.coroutines.Dispatchers
Expand Down Expand Up @@ -91,6 +101,7 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
}

private var myExposureKeysJSON: String? = null
private var myExposureKeys: List<TemporaryExposureKey>? = mutableListOf()
private var otherExposureKey: AppleLegacyKeyExchange.Key? = null
private var otherExposureKeyList = mutableListOf<AppleLegacyKeyExchange.Key>()

Expand All @@ -101,8 +112,12 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
// ViewModel for MainActivity
private val tracingViewModel: TracingViewModel by activityViewModels()

private lateinit var qrPager: ViewPager2
private lateinit var qrPagerAdapter: RecyclerView.Adapter<QRPagerAdapter.QRViewHolder>

// Data and View binding
private lateinit var binding: FragmentTestForAPIBinding
private var _binding: FragmentTestForAPIBinding? = null
private val binding: FragmentTestForAPIBinding get() = _binding!!

override fun onCreateView(
inflater: LayoutInflater,
Expand All @@ -111,7 +126,7 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
): View? {

// get the binding reference by inflating it with the current layout
binding = FragmentTestForAPIBinding.inflate(inflater)
_binding = FragmentTestForAPIBinding.inflate(inflater)

// set the viewmmodel variable that will be used for data binding
binding.tracingViewModel = tracingViewModel
Expand All @@ -123,6 +138,11 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
return binding.root
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

Expand All @@ -139,15 +159,24 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
internalExposureNotificationPermissionHelper =
InternalExposureNotificationPermissionHelper(this, this)

qrPager = qr_code_viewpager
qrPagerAdapter = QRPagerAdapter()
qrPager.adapter = qrPagerAdapter

button_api_test_start.setOnClickListener {
start()
}

button_api_get_exposure_keys.setOnClickListener {
getExposureKeys()
tracingViewModel.viewModelScope.launch {
ExposureSharingService.shareKeysAsBitmap(300, 300, updateQRImageView)
}
}

val last3HoursSwitch = test_api_switch_last_three_hours_from_server as Switch
last3HoursSwitch.isChecked = LocalData.last3HoursMode()
last3HoursSwitch.setOnClickListener {
val isLast3HoursModeEnabled = last3HoursSwitch.isChecked
showToast("Last 3 Hours Mode is activated: $isLast3HoursModeEnabled")
LocalData.last3HoursMode(isLast3HoursModeEnabled)
}

button_api_get_check_exposure.setOnClickListener {
Expand Down Expand Up @@ -241,13 +270,6 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
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 ->
StringBuilder()
.append("\nKey data: ${key.keyData}")
Expand Down Expand Up @@ -423,10 +445,6 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
)
label_my_keys.text = myKeysLabelAndCount
text_my_keys.text = myExposureKeysJSON

tracingViewModel.viewModelScope.launch {
ExposureSharingService.shareKeysAsBitmap(300, 300, updateQRImageView)
}
}

private fun showToast(message: String) {
Expand All @@ -445,6 +463,9 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
override fun onKeySharePermissionGranted(keys: List<TemporaryExposureKey>) {
myExposureKeysJSON =
keysToJson(keys)
myExposureKeys = keys
qrPagerAdapter.notifyDataSetChanged()

updateKeysDisplay()
}

Expand Down Expand Up @@ -491,4 +512,46 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
CONFIG_SCORE
)
.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
}
}
}
Loading

0 comments on commit 6d33c5b

Please sign in to comment.