├── .circleci └── config.yml ├── .gitignore ├── .gitmodules ├── .idea ├── .name ├── codeStyles │ └── Project.xml ├── gradle.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── LICENSE.md ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── edu │ │ └── example │ │ └── covidsafe │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── ic_help-playstore.png │ ├── java │ │ └── edu │ │ │ └── uw │ │ │ └── covidsafe │ │ │ ├── AppStatusManager.java │ │ │ ├── CovidSafeApplication.java │ │ │ ├── ble │ │ │ ├── BleDbRecordDao.java │ │ │ ├── BleDbRecordRepository.java │ │ │ ├── BleDbRecordRoomDatabase.java │ │ │ ├── BleOpsAsyncTask.java │ │ │ ├── BleRecord.java │ │ │ ├── BluetoothScanHelper.java │ │ │ ├── BluetoothServerHelper.java │ │ │ └── BluetoothUtils.java │ │ │ ├── broadcastreceivers │ │ │ └── AutoStartWorkReceiver.java │ │ │ ├── comms │ │ │ ├── NetworkConstant.java │ │ │ ├── NetworkHelper.java │ │ │ ├── PullFromServerTask.java │ │ │ ├── PullFromServerTaskDemo.java │ │ │ ├── PullFromServerTaskDemo2.java │ │ │ └── SendInfectedUserData.java │ │ │ ├── crypto │ │ │ ├── AES256.java │ │ │ ├── AESPair.java │ │ │ ├── ByteHelper.java │ │ │ ├── Constant.java │ │ │ ├── RSA.java │ │ │ └── SHA256.java │ │ │ ├── gps │ │ │ ├── GpsDbModel.java │ │ │ ├── GpsDbRecordDao.java │ │ │ ├── GpsDbRecordRepository.java │ │ │ ├── GpsDbRecordRoomDatabase.java │ │ │ ├── GpsHistoryRecyclerViewAdapter.java │ │ │ ├── GpsOpsAsyncTask.java │ │ │ ├── GpsRecord.java │ │ │ ├── GpsUtils.java │ │ │ ├── ImportLocationHistoryFragment.java │ │ │ └── LocationDataXMLParser.java │ │ │ ├── json │ │ │ ├── Area.java │ │ │ ├── AreaMatch.java │ │ │ ├── BlueToothSeed.java │ │ │ ├── BluetoothMatch.java │ │ │ ├── Location.java │ │ │ ├── MatchMessage.java │ │ │ ├── MessageInfo.java │ │ │ ├── MessageListRequest.java │ │ │ ├── MessageListResponse.java │ │ │ ├── MessageRequest.java │ │ │ ├── MessageSizeRequest.java │ │ │ ├── MessageSizeResponse.java │ │ │ ├── Region.java │ │ │ ├── SelfReportRequest.java │ │ │ └── Status.java │ │ │ ├── models │ │ │ └── LatLng.java │ │ │ ├── preferences │ │ │ ├── AppPreferencesHelper.java │ │ │ └── LocaleHelper.java │ │ │ ├── seed_uuid │ │ │ ├── SeedUUIDDbRecordDao.java │ │ │ ├── SeedUUIDDbRecordRepository.java │ │ │ ├── SeedUUIDDbRecordRoomDatabase.java │ │ │ ├── SeedUUIDOpsAsyncTask.java │ │ │ ├── SeedUUIDRecord.java │ │ │ └── UUIDGeneratorTask.java │ │ │ ├── service │ │ │ └── LoggingService.java │ │ │ ├── ui │ │ │ ├── MainActivity.java │ │ │ ├── MainFragment.java │ │ │ ├── PermissionLogic.java │ │ │ ├── Splash.java │ │ │ ├── contact_log │ │ │ │ ├── ContactLogFragment.java │ │ │ │ ├── ContactLogPageAdapter.java │ │ │ │ ├── LocationFragment.java │ │ │ │ └── PeopleFragment.java │ │ │ ├── contact_trace │ │ │ │ ├── ContactPageAdapter.java │ │ │ │ ├── ContactStepFragment.java │ │ │ │ ├── ContactTraceFragment.java │ │ │ │ ├── GpsHistoryRecyclerViewAdapter2.java │ │ │ │ ├── HumanDbModel.java │ │ │ │ ├── HumanDbRecordDao.java │ │ │ │ ├── HumanDbRecordRepository.java │ │ │ │ ├── HumanDbRecordRoomDatabase.java │ │ │ │ ├── HumanOpsAsyncTask.java │ │ │ │ ├── HumanRecord.java │ │ │ │ ├── HumanSummaryRecyclerViewAdapter.java │ │ │ │ ├── NonSwipeableViewPager.java │ │ │ │ └── SymptomSummaryRecyclerViewAdapter2.java │ │ │ ├── faq │ │ │ │ ├── FaqFragment.java │ │ │ │ └── FaqRecyclerView.java │ │ │ ├── health │ │ │ │ ├── DiagnosisFragment.java │ │ │ │ ├── HealthFragment.java │ │ │ │ ├── HealthPageAdapter.java │ │ │ │ ├── ResourceRecyclerViewAdapter.java │ │ │ │ └── TipRecyclerViewAdapter.java │ │ │ ├── notif │ │ │ │ ├── HistoryRecyclerViewAdapter.java │ │ │ │ ├── NotifDbModel.java │ │ │ │ ├── NotifDbRecordDao.java │ │ │ │ ├── NotifDbRecordRepository.java │ │ │ │ ├── NotifDbRecordRoomDatabase.java │ │ │ │ ├── NotifOpsAsyncTask.java │ │ │ │ ├── NotifRecord.java │ │ │ │ └── NotifRecyclerViewAdapter.java │ │ │ ├── onboarding │ │ │ │ ├── OnboardingActivity.java │ │ │ │ ├── OnboardingStateAdapter.java │ │ │ │ ├── PagerFragment.java │ │ │ │ ├── PermissionFragment.java │ │ │ │ └── StoryFragment.java │ │ │ ├── settings │ │ │ │ ├── MiscRecyclerViewAdapter.java │ │ │ │ ├── MoreRecyclerViewAdapter.java │ │ │ │ ├── PermUtils.java │ │ │ │ ├── PermissionsRecyclerViewAdapter.java │ │ │ │ ├── SettingsFragment.java │ │ │ │ └── TraceSettingsRecyclerViewAdapter.java │ │ │ └── symptoms │ │ │ │ ├── AddEditSymptomsFragment.java │ │ │ │ ├── SymptomConfirmFragment.java │ │ │ │ ├── SymptomDbModel.java │ │ │ │ ├── SymptomHistoryRecyclerViewAdapter.java │ │ │ │ ├── SymptomRecyclerViewAdapter.java │ │ │ │ ├── SymptomSummaryRecyclerViewAdapter.java │ │ │ │ ├── SymptomTrackerFragment.java │ │ │ │ ├── SymptomUtils.java │ │ │ │ ├── SymptomsDbRecordDao.java │ │ │ │ ├── SymptomsDbRecordRepository.java │ │ │ │ ├── SymptomsDbRecordRoomDatabase.java │ │ │ │ ├── SymptomsOpsAsyncTask.java │ │ │ │ └── SymptomsRecord.java │ │ │ ├── utils │ │ │ ├── ByteUtils.java │ │ │ ├── Constants.java │ │ │ ├── CryptoUtils.java │ │ │ ├── FileOperations.java │ │ │ ├── RegenerateSeedUponReport.java │ │ │ ├── TimeUtils.java │ │ │ └── Utils.java │ │ │ └── workmanager │ │ │ ├── periodictasks │ │ │ └── PeriodicTasksHandler.java │ │ │ └── workers │ │ │ ├── BluetoothScanWorker.java │ │ │ ├── LogPurgerWorker.java │ │ │ ├── PullFromServerWorker.java │ │ │ └── UUIDGeneratorWorker.java │ ├── res │ │ ├── anim │ │ │ ├── enter_bottom_to_top.xml │ │ │ ├── enter_left_to_right.xml │ │ │ ├── enter_right_to_left.xml │ │ │ ├── enter_top_to_bottom.xml │ │ │ ├── exit_left_to_right.xml │ │ │ ├── exit_right_to_left.xml │ │ │ ├── exit_top_to_bottom.xml │ │ │ └── no_anim.xml │ │ ├── color │ │ │ └── cal_color.xml │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xxhdpi │ │ │ ├── onboard1.png │ │ │ ├── onboard2.png │ │ │ ├── onboard3.png │ │ │ ├── onboard4.png │ │ │ ├── onboard5.png │ │ │ ├── splashlogo.png │ │ │ └── uwbanner.png │ │ ├── drawable │ │ │ ├── active.png │ │ │ ├── avatar.png │ │ │ ├── calendar.png │ │ │ ├── calendar_highlighted.png │ │ │ ├── check.png │ │ │ ├── check2.png │ │ │ ├── clipboard.png │ │ │ ├── clock.png │ │ │ ├── contact.png │ │ │ ├── contacticon.png │ │ │ ├── current_1.png │ │ │ ├── current_2.png │ │ │ ├── current_3.png │ │ │ ├── current_4.png │ │ │ ├── datalength.png │ │ │ ├── deactive.png │ │ │ ├── done_1.png │ │ │ ├── done_2.png │ │ │ ├── done_3.png │ │ │ ├── ic_add_black_24dp.xml │ │ │ ├── ic_add_gray_24dp.xml │ │ │ ├── ic_add_white_24dp.xml │ │ │ ├── ic_android_black_24dp.xml │ │ │ ├── ic_arrow_back_black_24dp.xml │ │ │ ├── ic_chevron_right_gray_24dp.xml │ │ │ ├── ic_close_black_24dp.xml │ │ │ ├── ic_delete_black_24dp.xml │ │ │ ├── ic_delete_gray_24dp.xml │ │ │ ├── ic_edit_black_24dp.xml │ │ │ ├── ic_edit_gray_24dp.xml │ │ │ ├── ic_file_download_black_24dp.xml │ │ │ ├── ic_help.xml │ │ │ ├── ic_history_black_24dp.xml │ │ │ ├── ic_info_black_24dp.xml │ │ │ ├── ic_info_outline_black_24dp.xml │ │ │ ├── ic_keyboard_arrow_down_black_24dp.xml │ │ │ ├── ic_keyboard_arrow_down_gray_24dp.xml │ │ │ ├── ic_language_black_24dp.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── ic_lock_black_24dp.xml │ │ │ ├── ic_more_vert_black_24dp.xml │ │ │ ├── ic_more_vert_gray_24dp.xml │ │ │ ├── ic_my_location_black_24dp.xml │ │ │ ├── ic_navigate_before_black_24dp.xml │ │ │ ├── ic_navigate_next_black_24dp.xml │ │ │ ├── ic_refresh_black_24dp.xml │ │ │ ├── ic_send_black_24dp.xml │ │ │ ├── ic_settings_black_24dp.xml │ │ │ ├── ic_warning_black_24dp.xml │ │ │ ├── icon_broadcast.png │ │ │ ├── icon_faq.png │ │ │ ├── icon_faq2.png │ │ │ ├── icon_health.png │ │ │ ├── icon_phone.png │ │ │ ├── icon_phone2.png │ │ │ ├── icon_phone3.png │ │ │ ├── icon_quarantine.png │ │ │ ├── icon_share.png │ │ │ ├── icon_share2.png │ │ │ ├── icon_symptoms.png │ │ │ ├── icon_test.png │ │ │ ├── importicon.png │ │ │ ├── kclogo.jpg │ │ │ ├── lang.png │ │ │ ├── logo.png │ │ │ ├── logo2.png │ │ │ ├── logo_purple.png │ │ │ ├── map.png │ │ │ ├── map_header.png │ │ │ ├── mapicon.png │ │ │ ├── microsoftlogo.png │ │ │ ├── nav1.png │ │ │ ├── nav2.png │ │ │ ├── nav3.png │ │ │ ├── onboard1.png │ │ │ ├── onboard2.png │ │ │ ├── onboard3.png │ │ │ ├── onboard4.png │ │ │ ├── onboard5.png │ │ │ ├── people.png │ │ │ ├── perm1.png │ │ │ ├── perm2.png │ │ │ ├── perm3.png │ │ │ ├── person.png │ │ │ ├── rect.png │ │ │ ├── rect2.png │ │ │ ├── rect3.png │ │ │ ├── report.png │ │ │ ├── res1.png │ │ │ ├── res2.png │ │ │ ├── ring.png │ │ │ ├── rubbish.png │ │ │ ├── settings_black.png │ │ │ ├── settings_white.png │ │ │ ├── shadows.xml │ │ │ ├── speech.png │ │ │ ├── speech_icon.png │ │ │ ├── splashlogo.png │ │ │ ├── startbutton.xml │ │ │ ├── stopbutton.xml │ │ │ ├── switch_off.png │ │ │ ├── switch_on.png │ │ │ ├── switch_on_noring.png │ │ │ ├── symptom_confirm.png │ │ │ ├── symptom_confirm_header.png │ │ │ ├── symptom_done.png │ │ │ ├── symptom_edit.png │ │ │ ├── symptom_recent.png │ │ │ ├── todo_2.png │ │ │ ├── todo_3.png │ │ │ ├── todo_4.png │ │ │ ├── uwbanner.png │ │ │ ├── uwlogopurple.png │ │ │ ├── uwlogowhite.png │ │ │ ├── warning.png │ │ │ ├── warning2.png │ │ │ └── warning3.png │ │ ├── layout │ │ │ ├── activity_main.xml │ │ │ ├── activity_onboarding.xml │ │ │ ├── add_symptoms_fragment.xml │ │ │ ├── card_action.xml │ │ │ ├── card_broadcast.xml │ │ │ ├── card_call.xml │ │ │ ├── card_cough.xml │ │ │ ├── card_data_storage.xml │ │ │ ├── card_fever.xml │ │ │ ├── card_gps_history.xml │ │ │ ├── card_history.xml │ │ │ ├── card_human.xml │ │ │ ├── card_misc.xml │ │ │ ├── card_more.xml │ │ │ ├── card_notification.xml │ │ │ ├── card_permission.xml │ │ │ ├── card_privacy_disclaimer.xml │ │ │ ├── card_privacy_disclaimer2.xml │ │ │ ├── card_privacy_disclaimer3.xml │ │ │ ├── card_resource.xml │ │ │ ├── card_spinner_setting.xml │ │ │ ├── card_symptom_log_recent.xml │ │ │ ├── card_symptom_reminder.xml │ │ │ ├── card_tracer_interview.xml │ │ │ ├── card_upload.xml │ │ │ ├── checkbox.xml │ │ │ ├── contact_trace_pager.xml │ │ │ ├── contact_trace_step.xml │ │ │ ├── contact_view.xml │ │ │ ├── contract_trace_start.xml │ │ │ ├── faq_answer.xml │ │ │ ├── faq_question.xml │ │ │ ├── faq_row.xml │ │ │ ├── fragment_contact_log.xml │ │ │ ├── fragment_faq.xml │ │ │ ├── fragment_faq2.xml │ │ │ ├── fragment_history.xml │ │ │ ├── fragment_import.xml │ │ │ ├── fragment_locations.xml │ │ │ ├── fragment_main.xml │ │ │ ├── fragment_main_old.xml │ │ │ ├── fragment_people.xml │ │ │ ├── fragment_settings.xml │ │ │ ├── fragment_symptom_confirmation.xml │ │ │ ├── gps_history_log.xml │ │ │ ├── health_diagnosis.xml │ │ │ ├── health_diagnosis_old.xml │ │ │ ├── health_main.xml │ │ │ ├── health_main_old.xml │ │ │ ├── health_start_diagnosis.xml │ │ │ ├── health_symptom_tracker.xml │ │ │ ├── health_symptom_tracker_old.xml │ │ │ ├── import_view.xml │ │ │ ├── layout_indicator.xml │ │ │ ├── onboarding_permissions.xml │ │ │ ├── onboarding_start.xml │ │ │ ├── onboarding_start_old.xml │ │ │ ├── onboarding_story.xml │ │ │ ├── onboarding_story_fragment.xml │ │ │ ├── resource_links.xml │ │ │ ├── splash.xml │ │ │ ├── symptom_buttons.xml │ │ │ ├── symptom_confirm_card.xml │ │ │ ├── symptom_list_layout.xml │ │ │ └── symptom_summary_card.xml │ │ ├── menu │ │ │ ├── bottom_nav_menu_release.xml │ │ │ ├── mymenu.xml │ │ │ └── overflow_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ │ ├── ic_help.png │ │ │ ├── ic_help_round.png │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ ├── uw_logo.png │ │ │ ├── uw_logo_foreground.png │ │ │ └── uw_logo_round.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_help.png │ │ │ ├── ic_help_round.png │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ ├── uw_logo.png │ │ │ ├── uw_logo_foreground.png │ │ │ └── uw_logo_round.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_help.png │ │ │ ├── ic_help_round.png │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ ├── uw_logo.png │ │ │ ├── uw_logo_foreground.png │ │ │ └── uw_logo_round.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_help.png │ │ │ ├── ic_help_round.png │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ ├── uw_logo.png │ │ │ ├── uw_logo_foreground.png │ │ │ └── uw_logo_round.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_help.png │ │ │ ├── ic_help_round.png │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ ├── uw_logo.png │ │ │ ├── uw_logo_foreground.png │ │ │ └── uw_logo_round.png │ │ ├── raw │ │ │ ├── auth_config_single_account.json │ │ │ ├── device_data.csv │ │ │ └── loc.xml │ │ ├── values-es │ │ │ └── strings.xml │ │ ├── values-v23 │ │ │ └── styles.xml │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── xml │ │ │ ├── appcenter_backup_rule.xml │ │ │ └── network_security_config.xml │ └── uw_logo-playstore.png │ └── test │ └── java │ └── edu │ └── uw │ └── covidsafe │ ├── ExampleUnitTest.java │ ├── comms │ ├── PullFromServerTaskTest.java │ ├── QueryBuilderTest.java │ └── SendInfectedUserDataTest.java │ ├── crypto │ ├── TestAES256.java │ ├── TestBase64Conversions.java │ ├── TestRSA.java │ └── TestSHA256.java │ ├── json │ └── MessageSizeResponseTest.java │ ├── performance │ └── UUIDTest.java │ └── utils │ ├── CryptoUtilsTest.java │ └── TimeUtilsTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── imgs ├── logo-big.png ├── logo-small.png └── logo_purple2.png └── settings.gradle /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | working_directory: ~/code 5 | docker: 6 | - image: circleci/android:api-25 7 | environment: 8 | JVM_OPTS: -Xmx4G 9 | steps: 10 | - restore_cache: 11 | key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }} 12 | - checkout 13 | - run: 14 | name: "Pull Required Submodules" 15 | command: | 16 | git submodule init 17 | git submodule update --remote 18 | - run: 19 | name: Download Project Build Dependencies 20 | command: ./gradlew androidDependencies 21 | - save_cache: 22 | paths: 23 | - ~/.gradle 24 | key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }} 25 | - run: 26 | name: Run Build and Tests 27 | command: ./gradlew build test 28 | - store_test_results: 29 | path: app/build/test-results 30 | destination: test-results/ 31 | - run: 32 | name: Initial build 33 | command: ./gradlew clean assembleRelease --no-daemon --stacktrace 34 | - store_artifacts: 35 | path: app/build/outputs/apk/ 36 | destination: apks/ 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | keystore.properties -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "app/src/main/proto"] 2 | path = app/src/main/proto 3 | url = git@github.com:covidsafe/proto.git 4 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | covidsafe -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 1.8 19 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2020 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/edu/example/covidsafe/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package edu.example.covidsafe; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | import androidx.test.platform.app.InstrumentationRegistry; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.example.corona", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/ic_help-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/ic_help-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/AppStatusManager.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe; 2 | 3 | import android.text.SpannableStringBuilder; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | 7 | import com.google.android.material.snackbar.Snackbar; 8 | 9 | public class AppStatusManager { 10 | 11 | public Snackbar getmSnackBar() { 12 | return mSnackBar; 13 | } 14 | 15 | Snackbar mSnackBar; 16 | View.OnClickListener onClickListener; 17 | String actionText; 18 | 19 | public AppStatusManager() { 20 | mSnackBar = null; 21 | onClickListener = null; 22 | actionText = null; 23 | } 24 | 25 | public AppStatusManager makeSnackBar(View view, 26 | SpannableStringBuilder stringBuilder, 27 | int snackbarDuration) { 28 | if (view != null && stringBuilder != null) { 29 | mSnackBar = Snackbar.make(view, stringBuilder, snackbarDuration); 30 | } 31 | return this; 32 | } 33 | 34 | public AppStatusManager makeSnackBar(View view, 35 | String stringText, 36 | int snackbarDuration) { 37 | if (view != null && stringText != null) { 38 | mSnackBar = Snackbar.make(view, stringText, snackbarDuration); 39 | } 40 | return this; 41 | } 42 | 43 | public AppStatusManager setAction(String actionText, View.OnClickListener onClickListener) { 44 | if(mSnackBar != null && actionText != null && onClickListener != null){ 45 | mSnackBar.setAction(actionText, onClickListener); 46 | } 47 | return this; 48 | } 49 | 50 | public void show() { 51 | if (mSnackBar != null) { 52 | View snackbarView = mSnackBar.getView(); 53 | if (snackbarView != null) { 54 | TextView textView = (TextView) snackbarView.findViewById(com.google.android.material.R.id.snackbar_text); 55 | textView.setMaxLines(5); 56 | 57 | mSnackBar.show(); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/CovidSafeApplication.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe; 2 | 3 | import android.app.Application; 4 | import android.app.NotificationChannel; 5 | import android.app.NotificationManager; 6 | import android.os.Build; 7 | 8 | import edu.uw.covidsafe.workmanager.periodictasks.PeriodicTasksHandler; 9 | 10 | public class CovidSafeApplication extends Application { 11 | 12 | public static final String LOGGING_SERVICE_CHANNEL_ID = "loggingServiceChannel"; 13 | 14 | @Override 15 | public void onCreate() { 16 | super.onCreate(); 17 | createNotificationChannels(); 18 | PeriodicTasksHandler periodicTasksHandler = new PeriodicTasksHandler(this); 19 | periodicTasksHandler.initAllPeriodicRequests(); 20 | } 21 | 22 | private void createNotificationChannels() { 23 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 24 | NotificationChannel loggingServiceChannel = new NotificationChannel(LOGGING_SERVICE_CHANNEL_ID, 25 | "LoggingServiceChannel", NotificationManager.IMPORTANCE_HIGH); 26 | 27 | NotificationManager manager = getSystemService(NotificationManager.class); 28 | if (manager != null) { 29 | manager.createNotificationChannel(loggingServiceChannel); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ble/BleDbRecordDao.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ble; 2 | 3 | import androidx.room.Dao; 4 | import androidx.room.Insert; 5 | import androidx.room.OnConflictStrategy; 6 | import androidx.room.Query; 7 | 8 | import java.util.List; 9 | 10 | @Dao 11 | public interface BleDbRecordDao { 12 | 13 | @Query("SELECT * FROM ble_record_table") 14 | List getAllRecords(); 15 | 16 | // allowing the insert of the same word multiple times by passing a 17 | // conflict resolution strategy 18 | @Insert(onConflict = OnConflictStrategy.REPLACE) 19 | void insert(BleRecord record); 20 | 21 | @Query("DELETE FROM ble_record_table") 22 | void deleteAll(); 23 | 24 | @Query("DELETE FROM ble_record_table WHERE ts <= :ts_thresh") 25 | void deleteEarlierThan(long ts_thresh); 26 | 27 | @Query("SELECT * FROM ble_record_table ORDER BY ts DESC") 28 | List getSortedRecordsByTimestamp(); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ble/BleDbRecordRepository.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ble; 2 | 3 | import android.content.Context; 4 | 5 | import java.util.List; 6 | 7 | public class BleDbRecordRepository { 8 | private BleDbRecordDao mRecordDao; 9 | 10 | // Note that in order to unit test the WordRepository, you have to remove the Application 11 | // dependency. This adds complexity and much more code, and this sample is not about testing. 12 | // See the BasicSample in the android-architecture-components repository at 13 | // https://github.com/googlesamples 14 | public BleDbRecordRepository(Context application) { 15 | BleDbRecordRoomDatabase db = BleDbRecordRoomDatabase.getDatabase(application); 16 | mRecordDao = db.recordDao(); 17 | // mAllRecords = mRecordDao.getSortedRecords(); 18 | } 19 | 20 | // Room executes all queries on a separate thread. 21 | // Observed LiveData will notify the observer when the data has changed. 22 | public List getAllRecords() { 23 | return mRecordDao.getSortedRecordsByTimestamp(); 24 | } 25 | 26 | // You must call this on a non-UI thread or your app will throw an exception. Room ensures 27 | // that you're not doing any long running operations on the main thread, blocking the UI. 28 | public void insert(BleRecord record) { 29 | BleDbRecordRoomDatabase.databaseWriteExecutor.execute(() -> { 30 | mRecordDao.insert(record); 31 | }); 32 | } 33 | 34 | public void deleteAll() { 35 | mRecordDao.deleteAll(); 36 | } 37 | 38 | public void deleteEarlierThan(long ts_thresh) { 39 | mRecordDao.deleteEarlierThan(ts_thresh); 40 | } 41 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ble/BleDbRecordRoomDatabase.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ble; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.room.Database; 7 | import androidx.room.Room; 8 | import androidx.room.RoomDatabase; 9 | import androidx.sqlite.db.SupportSQLiteDatabase; 10 | 11 | import java.util.concurrent.ExecutorService; 12 | import java.util.concurrent.Executors; 13 | 14 | @Database(entities = {BleRecord.class}, version = 1, exportSchema = false) 15 | public abstract class BleDbRecordRoomDatabase extends RoomDatabase { 16 | 17 | private static final int NUMBER_OF_THREADS = 4; 18 | static final ExecutorService databaseWriteExecutor = 19 | Executors.newFixedThreadPool(NUMBER_OF_THREADS); 20 | private static volatile BleDbRecordRoomDatabase INSTANCE; 21 | private static RoomDatabase.Callback sRoomDatabaseCallback = new RoomDatabase.Callback() { 22 | @Override 23 | public void onOpen(@NonNull SupportSQLiteDatabase db) { 24 | super.onOpen(db); 25 | 26 | // If you want to keep data through app restarts, 27 | // comment out the following block 28 | // databaseWriteExecutor.execute(() -> { 29 | // // Populate the database in the background. 30 | // // If you want to start with more words, just add them. 31 | // RecordDao dao = INSTANCE.recordDao(); 32 | // dao.deleteAll(); 33 | 34 | // Record word = new Record(System.currentTimeMillis(), 0.04f, false); 35 | // dao.insert(word); 36 | // }); 37 | } 38 | }; 39 | 40 | static BleDbRecordRoomDatabase getDatabase(final Context context) { 41 | if (INSTANCE == null) { 42 | synchronized (BleDbRecordRoomDatabase.class) { 43 | if (INSTANCE == null) { 44 | INSTANCE = Room.databaseBuilder(context, 45 | BleDbRecordRoomDatabase.class, "ble_record_database") 46 | .build(); 47 | } 48 | } 49 | } 50 | 51 | return INSTANCE; 52 | } 53 | 54 | public abstract BleDbRecordDao recordDao(); 55 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ble/BleOpsAsyncTask.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ble; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | import android.util.Log; 6 | 7 | import java.util.List; 8 | 9 | import edu.uw.covidsafe.utils.Constants; 10 | 11 | public class BleOpsAsyncTask extends AsyncTask { 12 | private BleDbRecordRepository repo; 13 | private BleRecord result; 14 | private Constants.BleDatabaseOps op; 15 | 16 | public BleOpsAsyncTask(Context cxt, String id, int rssi, long ts, int model) { 17 | repo = new BleDbRecordRepository(cxt); 18 | this.result = new BleRecord(id, ts, rssi, model); 19 | this.op = Constants.BleDatabaseOps.Insert; 20 | } 21 | 22 | public BleOpsAsyncTask(Context cxt, Constants.BleDatabaseOps op) { 23 | repo = new BleDbRecordRepository(cxt); 24 | this.op = op; 25 | } 26 | 27 | @Override 28 | protected Void doInBackground(Void... params) { 29 | Log.e("ble","doinbackground ble "+this.op); 30 | if (this.op == Constants.BleDatabaseOps.Insert) { 31 | repo.insert(this.result); 32 | // if (Constants.WRITE_TO_DISK) { 33 | // Utils.bleLogToFile(this.context, this.result); 34 | // } 35 | } 36 | else if (this.op == Constants.BleDatabaseOps.ViewAll) { 37 | List records = repo.getAllRecords(); 38 | for (BleRecord record : records) { 39 | Log.e("ble",record.toString()); 40 | } 41 | } 42 | else if (this.op == Constants.BleDatabaseOps.DeleteAll) { 43 | repo.deleteAll(); 44 | } 45 | return null; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ble/BleRecord.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ble; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.room.ColumnInfo; 5 | import androidx.room.Entity; 6 | import androidx.room.PrimaryKey; 7 | 8 | import java.text.SimpleDateFormat; 9 | import java.util.Date; 10 | 11 | @Entity(tableName = "ble_record_table") 12 | public class BleRecord { 13 | 14 | @PrimaryKey 15 | @NonNull 16 | @ColumnInfo(name = "uuid") 17 | private String uuid; 18 | 19 | @NonNull 20 | @ColumnInfo(name = "ts") 21 | private long ts; 22 | 23 | @NonNull 24 | @ColumnInfo(name = "rssi") 25 | private int rssi; 26 | 27 | @NonNull 28 | @ColumnInfo(name = "model") 29 | private int model; 30 | 31 | public BleRecord(@NonNull String ss) { 32 | String[] elts = ss.split(","); 33 | this.uuid = elts[0]; 34 | this.ts = Long.parseLong(elts[1]); 35 | this.rssi = Integer.parseInt(elts[2]); 36 | this.model = Integer.parseInt(elts[3]); 37 | } 38 | 39 | public BleRecord(@NonNull String uuid, long ts, int rssi, int model) { 40 | this.uuid = uuid; 41 | this.ts = ts; 42 | this.rssi = rssi; 43 | this.model = model; 44 | } 45 | 46 | public String getUuid() { return this.uuid; } 47 | 48 | public long getTs() { 49 | return this.ts; 50 | } 51 | 52 | public int getRssi() { return this.rssi; } 53 | 54 | public int getModel() { 55 | return model; 56 | } 57 | 58 | public void setModel(int model) { 59 | this.model = model; 60 | } 61 | 62 | public String toString() { 63 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 64 | Date d = new Date(this.ts); 65 | return this.uuid +","+sdf.format(d)+","+this.rssi; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/broadcastreceivers/AutoStartWorkReceiver.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.broadcastreceivers; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Build; 7 | 8 | import edu.uw.covidsafe.service.LoggingService; 9 | 10 | public class AutoStartWorkReceiver extends BroadcastReceiver { 11 | @Override 12 | public void onReceive(Context context, Intent intent) { 13 | 14 | if (intent.getAction() != null && intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { 15 | Intent serviceIntent = new Intent(context, LoggingService.class); 16 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 17 | context.startForegroundService(serviceIntent); 18 | } else { 19 | context.startService(serviceIntent); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/comms/NetworkConstant.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.comms; 2 | 3 | import android.app.Activity; 4 | 5 | import com.android.volley.Cache; 6 | import com.android.volley.Network; 7 | import com.android.volley.RequestQueue; 8 | import com.android.volley.toolbox.BasicNetwork; 9 | import com.android.volley.toolbox.DiskBasedCache; 10 | import com.android.volley.toolbox.HurlStack; 11 | import com.google.gson.Gson; 12 | 13 | public class NetworkConstant { 14 | public static String BASE_URL = "https://csapi.azurefd.net/api/"; 15 | public static String API_VERSION = "2020-04-15"; 16 | public static int TIMEOUT = 10; 17 | static RequestQueue requestQueue; 18 | static Gson gson; 19 | 20 | public static void init(Activity av) { 21 | gson = new Gson(); 22 | // Instantiate the cache 23 | Cache cache = new DiskBasedCache(av.getCacheDir(), 1024 * 1024); // 1MB cap 24 | 25 | // Set up the network to use HttpURLConnection as the HTTP client. 26 | Network network = new BasicNetwork(new HurlStack()); 27 | 28 | // Instantiate the RequestQueue with the cache and network. 29 | requestQueue = new RequestQueue(cache, network); 30 | 31 | // Start the queue 32 | requestQueue.start(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/crypto/AESPair.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.crypto; 2 | 3 | import javax.crypto.SecretKey; 4 | 5 | public class AESPair { 6 | private SecretKey key; 7 | private byte[] IV; 8 | 9 | public void setIV(byte[] IV) { 10 | this.IV = IV; 11 | } 12 | 13 | public void setKey(SecretKey key) { 14 | this.key = key; 15 | } 16 | 17 | public byte[] getIV() { 18 | return IV; 19 | } 20 | 21 | public SecretKey getKey() { 22 | return key; 23 | } 24 | 25 | public AESPair(SecretKey sk, byte[] ivBytes) { 26 | key = sk; 27 | IV = ivBytes; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/crypto/ByteHelper.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.crypto; 2 | 3 | import java.util.List; 4 | 5 | public class ByteHelper { 6 | private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); 7 | // Convert byte[] to Hex encoding 8 | public static String convertBytesToHex(byte[] bytes) { 9 | char[] hexChars = new char[bytes.length * 2]; 10 | for ( int j = 0; j < bytes.length; j++ ) { 11 | int v = bytes[j] & 0xFF; 12 | hexChars[j * 2] = hexArray[v >>> 4]; 13 | hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 14 | } 15 | return new String(hexChars).toLowerCase(); 16 | } 17 | 18 | // Convert Hex to byte[]{32} 19 | public static byte[] hexStringToByteArray(String hexString){ 20 | byte[] bytes = new byte[hexString.length() / 2]; 21 | 22 | for(int i = 0; i < hexString.length(); i += 2){ 23 | String sub = hexString.substring(i, i + 2); 24 | Integer intVal = Integer.parseInt(sub, 16); 25 | bytes[i / 2] = intVal.byteValue(); 26 | String hex = "".format("0x%x", bytes[i / 2]); 27 | } 28 | return bytes; 29 | } 30 | 31 | // concat byte arrays 32 | private static byte[] byteConcat(byte[] a, byte[] b) { 33 | byte[] c = new byte[a.length + b.length]; 34 | System.arraycopy(a,0,c,0,a.length); 35 | System.arraycopy(b,0,c,a.length, b.length); 36 | return c; 37 | } 38 | 39 | public static byte[] concat(List byteArray) { 40 | byte[] byteBuffer = new byte[0]; 41 | for (byte[] b : byteArray) { 42 | byteBuffer = byteConcat(byteBuffer, b); 43 | } 44 | return byteBuffer; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/crypto/Constant.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.crypto; 2 | 3 | public class Constant { 4 | public static final String ONE_WAY_HASH = "SHA-256"; 5 | public static final String AES = "AES"; // Uses CBC by default. 6 | 7 | // Note this is actually not ECB. There is no ECB in RSA. 8 | public static final String RSA_CIPHER = "RSA/ECB/PKCS1Padding"; 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/gps/GpsDbModel.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.gps; 2 | 3 | import android.app.Application; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.lifecycle.AndroidViewModel; 7 | import androidx.lifecycle.LiveData; 8 | 9 | import java.util.List; 10 | 11 | public class GpsDbModel extends AndroidViewModel { 12 | GpsDbRecordRepository repo; 13 | public LiveData> records; 14 | public GpsDbModel(@NonNull Application application) { 15 | super(application); 16 | repo = new GpsDbRecordRepository(application); 17 | records = repo.getSortedRecords(); 18 | } 19 | 20 | public LiveData> getAllSorted() { 21 | return records; 22 | } 23 | 24 | public void deleteAll() {repo.deleteAll();} 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/gps/GpsDbRecordDao.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.gps; 2 | 3 | import androidx.lifecycle.LiveData; 4 | import androidx.room.Dao; 5 | import androidx.room.Insert; 6 | import androidx.room.OnConflictStrategy; 7 | import androidx.room.Query; 8 | 9 | import java.util.List; 10 | 11 | @Dao 12 | public interface GpsDbRecordDao { 13 | 14 | @Query("SELECT * from gps_record_table") 15 | List getAllRecords(); 16 | 17 | // allowing the insert of the same word multiple times by passing a 18 | // conflict resolution strategy 19 | @Insert(onConflict = OnConflictStrategy.IGNORE) 20 | void insert(GpsRecord record); 21 | 22 | @Query("DELETE FROM gps_record_table") 23 | void deleteAll(); 24 | 25 | @Query("DELETE FROM gps_record_table WHERE ts_start == :ts") 26 | void delete(long ts); 27 | 28 | @Query("DELETE FROM gps_record_table WHERE ts_start <= :ts_thresh") 29 | void deleteEarlierThan(long ts_thresh); 30 | 31 | @Query("SELECT * from gps_record_table ORDER BY ts_start DESC") 32 | LiveData> getSortedRecords(); 33 | 34 | @Query("SELECT * from gps_record_table ORDER BY ts_start DESC") 35 | List getSortedRecordsSync(); 36 | 37 | @Query("SELECT * from gps_record_table WHERE ts_start BETWEEN :ts1 AND :ts2") 38 | List getRecordsBetweenTimestamp(long ts1, long ts2); 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/gps/GpsDbRecordRepository.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.gps; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.WorkerThread; 6 | import androidx.lifecycle.LiveData; 7 | 8 | import java.util.List; 9 | 10 | public class GpsDbRecordRepository { 11 | private GpsDbRecordDao mRecordDao; 12 | 13 | // Note that in order to unit test the WordRepository, you have to remove the Application 14 | // dependency. This adds complexity and much more code, and this sample is not about testing. 15 | // See the BasicSample in the android-architecture-components repository at 16 | // https://github.com/googlesamples 17 | public GpsDbRecordRepository(Context application) { 18 | GpsDbRecordRoomDatabase db = GpsDbRecordRoomDatabase.getDatabase(application); 19 | mRecordDao = db.recordDao(); 20 | } 21 | 22 | // Room executes all queries on a separate thread. 23 | // Observed LiveData will notify the observer when the data has changed. 24 | public List getAllRecords() { 25 | return mRecordDao.getAllRecords(); 26 | } 27 | 28 | // Room executes all queries on a separate thread. 29 | // Observed LiveData will notify the observer when the data has changed. 30 | public LiveData> getSortedRecords() { 31 | return mRecordDao.getSortedRecords(); 32 | } 33 | 34 | @WorkerThread 35 | public List getSortedRecordsSync() { 36 | return mRecordDao.getSortedRecordsSync(); 37 | } 38 | 39 | public List getRecordsBetweenTimestamps(long ts1, long ts2) { 40 | return mRecordDao.getRecordsBetweenTimestamp(ts1, ts2); 41 | } 42 | 43 | // You must call this on a non-UI thread or your app will throw an exception. Room ensures 44 | // that you're not doing any long running operations on the main thread, blocking the UI. 45 | public void insert(GpsRecord record) { 46 | GpsDbRecordRoomDatabase.databaseWriteExecutor.execute(() -> { 47 | mRecordDao.insert(record); 48 | }); 49 | } 50 | 51 | public void deleteAll() { 52 | mRecordDao.deleteAll(); 53 | } 54 | 55 | public void delete(long ts) { 56 | mRecordDao.delete(ts); 57 | } 58 | 59 | public void deleteEarlierThan(long ts_thresh) { 60 | mRecordDao.deleteEarlierThan(ts_thresh); 61 | } 62 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/gps/GpsDbRecordRoomDatabase.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.gps; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.room.Database; 7 | import androidx.room.Room; 8 | import androidx.room.RoomDatabase; 9 | import androidx.sqlite.db.SupportSQLiteDatabase; 10 | 11 | import java.util.concurrent.ExecutorService; 12 | import java.util.concurrent.Executors; 13 | 14 | @Database(entities = {GpsRecord.class}, version = 1, exportSchema = false) 15 | public abstract class GpsDbRecordRoomDatabase extends RoomDatabase { 16 | 17 | private static final int NUMBER_OF_THREADS = 4; 18 | static final ExecutorService databaseWriteExecutor = 19 | Executors.newFixedThreadPool(NUMBER_OF_THREADS); 20 | private static volatile GpsDbRecordRoomDatabase INSTANCE; 21 | private static RoomDatabase.Callback sRoomDatabaseCallback = new RoomDatabase.Callback() { 22 | @Override 23 | public void onOpen(@NonNull SupportSQLiteDatabase db) { 24 | super.onOpen(db); 25 | 26 | // If you want to keep data through app restarts, 27 | // comment out the following block 28 | // databaseWriteExecutor.execute(() -> { 29 | // // Populate the database in the background. 30 | // // If you want to start with more words, just add them. 31 | // RecordDao dao = INSTANCE.recordDao(); 32 | // dao.deleteAll(); 33 | 34 | // Record word = new Record(System.currentTimeMillis(), 0.04f, false); 35 | // dao.insert(word); 36 | // }); 37 | } 38 | }; 39 | 40 | static GpsDbRecordRoomDatabase getDatabase(final Context context) { 41 | if (INSTANCE == null) { 42 | synchronized (GpsDbRecordRoomDatabase.class) { 43 | if (INSTANCE == null) { 44 | INSTANCE = Room.databaseBuilder(context, 45 | GpsDbRecordRoomDatabase.class, "gps_record_database") 46 | .build(); 47 | } 48 | } 49 | } 50 | 51 | return INSTANCE; 52 | } 53 | 54 | public abstract GpsDbRecordDao recordDao(); 55 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/Area.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | public class Area { 7 | public Location location; 8 | public float radiusMeters; 9 | public long beginTime; 10 | public long endTime; 11 | 12 | public Area() { 13 | 14 | } 15 | 16 | public Area(double lat, double longi, float radiusMeters, long btime, long etime) { 17 | this.location = new Location(lat, longi); 18 | this.radiusMeters = radiusMeters; 19 | this.beginTime = btime; 20 | this.endTime = etime; 21 | } 22 | 23 | public JSONObject toJson() throws JSONException { 24 | JSONObject area_match = new JSONObject(); 25 | area_match.put("location", location.toJson()); 26 | area_match.put("radiusMeters",radiusMeters); 27 | area_match.put("beginTime",beginTime); 28 | area_match.put("endTime",endTime); 29 | return area_match; 30 | } 31 | 32 | public static Area parse(JSONObject obj) throws JSONException { 33 | Area area = new Area(); 34 | if (obj.has("location")) { 35 | area.location = Location.parse(obj.getJSONObject("location")); 36 | } 37 | if (obj.has("radiusMeters")) { 38 | area.radiusMeters = (float)obj.getDouble("radiusMeters"); 39 | } 40 | if (obj.has("beginTime")) { 41 | area.beginTime = obj.getLong("beginTime"); 42 | } 43 | if (obj.has("endTime")) { 44 | area.endTime = obj.getLong("endTime"); 45 | } 46 | return area; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/AreaMatch.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONException; 5 | import org.json.JSONObject; 6 | 7 | import edu.uw.covidsafe.comms.NetworkConstant; 8 | 9 | public class AreaMatch { 10 | 11 | public Area[] areas; 12 | public String userMessage; 13 | 14 | public JSONObject toJson() throws JSONException { 15 | JSONObject area_match = new JSONObject(); 16 | JSONArray arr = new JSONArray(); 17 | for (Area area : areas) { 18 | arr.put(area.toJson()); 19 | } 20 | area_match.put("areas", arr); 21 | area_match.put("userMessage", userMessage); 22 | return area_match; 23 | } 24 | 25 | public static AreaMatch parse(JSONObject obj) throws JSONException { 26 | AreaMatch areaMatch = new AreaMatch(); 27 | if (obj.has("areas")) { 28 | JSONArray array = obj.getJSONArray("areas"); 29 | areaMatch.areas = new Area[array.length()]; 30 | for (int i = 0; i < array.length(); i++) { 31 | areaMatch.areas[i] = Area.parse(array.getJSONObject(i)); 32 | } 33 | } 34 | if (obj.has("userMessage")) { 35 | areaMatch.userMessage = obj.getString("userMessage"); 36 | } 37 | return areaMatch; 38 | } 39 | 40 | public static String toHttpString() { 41 | return NetworkConstant.BASE_URL+"Messages/AreaReport?api-version="+NetworkConstant.API_VERSION; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/BlueToothSeed.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | public class BlueToothSeed { 7 | 8 | public String seed; 9 | public long sequenceStartTime; 10 | public long sequenceEndTime; 11 | 12 | public static BlueToothSeed parse(JSONObject obj) throws JSONException { 13 | BlueToothSeed bluetoothSeed = new BlueToothSeed(); 14 | if (obj.has("seed")) { 15 | bluetoothSeed.seed = obj.getString("seed"); 16 | } 17 | if (obj.has("sequenceStartTime")) { 18 | bluetoothSeed.sequenceStartTime = obj.getLong("sequenceStartTime"); 19 | } 20 | if (obj.has("sequenceEndTime")) { 21 | bluetoothSeed.sequenceEndTime = obj.getLong("sequenceEndTime"); 22 | } 23 | return bluetoothSeed; 24 | } 25 | 26 | public static JSONObject toJson(String seed, long ts_start, long ts_end) throws JSONException { 27 | JSONObject bluetooth_seed = new JSONObject(); 28 | bluetooth_seed.put("seed", seed); 29 | bluetooth_seed.put("sequenceStartTime", ts_start); 30 | bluetooth_seed.put("sequenceEndTime", ts_end); 31 | return bluetooth_seed; 32 | } 33 | 34 | public JSONObject toJson() throws JSONException { 35 | JSONObject bluetooth_seed = new JSONObject(); 36 | bluetooth_seed.put("seed", seed); 37 | bluetooth_seed.put("sequenceStartTime", sequenceStartTime); 38 | bluetooth_seed.put("sequenceEndTime", sequenceEndTime); 39 | return bluetooth_seed; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/BluetoothMatch.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONException; 5 | import org.json.JSONObject; 6 | 7 | public class BluetoothMatch { 8 | public String userMessage; 9 | public BlueToothSeed[] seeds; 10 | 11 | public static BluetoothMatch parse(JSONObject obj) throws JSONException { 12 | BluetoothMatch bluetoothMatch = new BluetoothMatch(); 13 | if (obj.has("seeds")) { 14 | JSONArray array = obj.getJSONArray("seeds"); 15 | bluetoothMatch.seeds = new BlueToothSeed[array.length()]; 16 | for (int i = 0; i < array.length(); i++) { 17 | bluetoothMatch.seeds[i] = BlueToothSeed.parse(array.getJSONObject(i)); 18 | } 19 | } 20 | if (obj.has("userMessage")) { 21 | bluetoothMatch.userMessage = obj.getString("userMessage"); 22 | } 23 | return bluetoothMatch; 24 | } 25 | 26 | public JSONObject toJson() throws JSONException { 27 | JSONObject bluetooth_match = new JSONObject(); 28 | JSONArray arr = new JSONArray(); 29 | for (BlueToothSeed seed : seeds) { 30 | arr.put(seed.toJson()); 31 | } 32 | bluetooth_match.put("seeds", arr); 33 | bluetooth_match.put("user_message", userMessage); 34 | return bluetooth_match; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/Location.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | public class Location { 7 | public double latitude; 8 | public double longitude; 9 | 10 | public Location() { 11 | 12 | } 13 | 14 | public Location(double latitude, double longitude) { 15 | this.latitude = latitude; 16 | this.longitude = longitude; 17 | } 18 | 19 | public JSONObject toJson() throws JSONException { 20 | JSONObject area_match = new JSONObject(); 21 | area_match.put("latitude", latitude); 22 | area_match.put("longitude",longitude); 23 | return area_match; 24 | } 25 | 26 | public static Location parse(JSONObject obj) throws JSONException { 27 | Location loc = new Location(); 28 | if (obj.has("latitude")) { 29 | loc.latitude = obj.getDouble("latitude"); 30 | } 31 | if (obj.has("longitude")) { 32 | loc.longitude = obj.getDouble("longitude"); 33 | } 34 | return loc; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/MatchMessage.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONException; 5 | import org.json.JSONObject; 6 | 7 | public class MatchMessage { 8 | public String boolExpression; 9 | public AreaMatch[] areaMatches; 10 | public BluetoothMatch[] bluetoothMatches; 11 | 12 | public JSONObject toJSON() throws JSONException { 13 | JSONObject matchMessage = new JSONObject(); 14 | 15 | if (bluetoothMatches != null) { 16 | JSONArray arr = new JSONArray(); 17 | for (BluetoothMatch bmatch : bluetoothMatches) { 18 | arr.put(bmatch.toJson()); 19 | } 20 | matchMessage.put("bluetoothMatches", arr); 21 | } 22 | 23 | if (areaMatches != null) { 24 | JSONArray arr2 = new JSONArray(); 25 | for (AreaMatch amatch : areaMatches) { 26 | arr2.put(amatch.toJson()); 27 | } 28 | matchMessage.put("areaMatches", arr2); 29 | } 30 | 31 | return matchMessage; 32 | } 33 | 34 | public static MatchMessage parse(JSONObject obj) throws JSONException { 35 | MatchMessage matchMessage = new MatchMessage(); 36 | if (obj.has("boolExpression")) { 37 | matchMessage.boolExpression = obj.getString("boolExpression"); 38 | } 39 | if (obj.has("areaMatches")) { 40 | JSONArray arr = obj.getJSONArray("areaMatches"); 41 | matchMessage.areaMatches = new AreaMatch[arr.length()]; 42 | for (int i = 0; i < arr.length(); i++) { 43 | matchMessage.areaMatches[i] = AreaMatch.parse(arr.getJSONObject(i)); 44 | } 45 | } 46 | if (obj.has("bluetoothMatches")) { 47 | JSONArray arr = obj.getJSONArray("bluetoothMatches"); 48 | matchMessage.bluetoothMatches = new BluetoothMatch[arr.length()]; 49 | for (int i = 0; i < arr.length(); i++) { 50 | matchMessage.bluetoothMatches[i] = BluetoothMatch.parse(arr.getJSONObject(i)); 51 | } 52 | } 53 | return matchMessage; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/MessageInfo.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | public class MessageInfo { 7 | public String MessageId; 8 | public long MessageTimestamp; 9 | 10 | public JSONObject toJson() throws JSONException { 11 | JSONObject obj = new JSONObject(); 12 | obj.put("MessageId", MessageId); 13 | obj.put("MessageTimestamp", MessageTimestamp); 14 | return obj; 15 | } 16 | 17 | public static MessageInfo parse(JSONObject obj) throws JSONException { 18 | MessageInfo messageInfo = new MessageInfo(); 19 | if (obj.has("messageId")) { 20 | messageInfo.MessageId = obj.getString("messageId"); 21 | } 22 | if (obj.has("messageTimestamp")) { 23 | messageInfo.MessageTimestamp = obj.getLong("messageTimestamp"); 24 | } 25 | return messageInfo; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/MessageListRequest.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | import edu.uw.covidsafe.comms.NetworkConstant; 7 | 8 | public class MessageListRequest { 9 | 10 | Region region; 11 | long last_query_time; 12 | 13 | public static MessageListRequest parse(JSONObject obj) throws JSONException { 14 | MessageListRequest messageListRequest = new MessageListRequest(); 15 | if (obj.has("region")) { 16 | messageListRequest.region = Region.parse(obj.getJSONObject("region")); 17 | } 18 | if (obj.has("last_query_time")) { 19 | messageListRequest.last_query_time = obj.getLong("last_query_time"); 20 | } 21 | return messageListRequest; 22 | } 23 | 24 | public static JSONObject toJson(double lat, double longi, int precision, long lastQueryTime) throws JSONException { 25 | JSONObject messageListRequest = new JSONObject(); 26 | messageListRequest.put("region", Region.toJson(lat, longi, precision)); 27 | messageListRequest.put("last_query_time", lastQueryTime); 28 | return messageListRequest; 29 | } 30 | 31 | public static String toHttpString(double lat, double longi, int precision, long lastQueryTime) { 32 | return NetworkConstant.BASE_URL+"Messages/"+String.format("List?lat=%f&lon=%f&precision=%d&lastTimestamp=%d&api-version=%s",lat,longi,precision,lastQueryTime,NetworkConstant.API_VERSION); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/MessageListResponse.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONException; 5 | import org.json.JSONObject; 6 | 7 | public class MessageListResponse { 8 | public MessageInfo[] messageInfo; 9 | public long query_time; 10 | public long maxResponseTimestamp = 0; 11 | 12 | public static MessageListResponse parse(JSONObject obj) throws JSONException { 13 | MessageListResponse messageListResponse = new MessageListResponse(); 14 | if (obj.has("messageInfoes")) { 15 | JSONArray arr = obj.getJSONArray("messageInfoes"); 16 | messageListResponse.messageInfo = new MessageInfo[arr.length()]; 17 | for (int i = 0; i < arr.length(); i++) { 18 | messageListResponse.messageInfo[i] = MessageInfo.parse(arr.getJSONObject(i)); 19 | } 20 | } 21 | if (obj.has("query_time")) { 22 | messageListResponse.query_time = obj.getLong("query_time"); 23 | } 24 | if (obj.has("maxResponseTimestamp")) { 25 | messageListResponse.maxResponseTimestamp = obj.getLong("maxResponseTimestamp"); 26 | } 27 | return messageListResponse; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/MessageRequest.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONException; 5 | import org.json.JSONObject; 6 | 7 | import edu.uw.covidsafe.comms.NetworkConstant; 8 | 9 | public class MessageRequest { 10 | 11 | MessageInfo[] RequestedQueries; 12 | 13 | public static MessageRequest parse(JSONObject obj) throws JSONException { 14 | MessageRequest messageRequest = new MessageRequest(); 15 | if (obj.has("RequestedQueries")) { 16 | JSONArray arr = obj.getJSONArray("RequestedQueries"); 17 | messageRequest.RequestedQueries = new MessageInfo[arr.length()]; 18 | for (int i = 0; i < arr.length(); i++) { 19 | messageRequest.RequestedQueries[i] = MessageInfo.parse(arr.getJSONObject(i)); 20 | } 21 | } 22 | return messageRequest; 23 | } 24 | 25 | public static JSONObject toJson(MessageInfo[] messageInfos) throws JSONException { 26 | JSONObject obj = new JSONObject(); 27 | JSONArray array = new JSONArray(); 28 | for (int i = 0; i < messageInfos.length; i++) { 29 | JSONObject obji = messageInfos[i].toJson(); 30 | array.put(i, obji); 31 | } 32 | obj.put("RequestedQueries", array); 33 | return obj; 34 | } 35 | 36 | public static String toHttpString() { 37 | return NetworkConstant.BASE_URL+"Message?api-version="+NetworkConstant.API_VERSION; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/MessageSizeRequest.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | import edu.uw.covidsafe.comms.NetworkConstant; 7 | 8 | public class MessageSizeRequest { 9 | 10 | Region region; 11 | long last_query_time; 12 | 13 | public static MessageSizeRequest parse(JSONObject obj) throws JSONException { 14 | MessageSizeRequest messageSizeRequest = new MessageSizeRequest(); 15 | if (obj.has("region")) { 16 | messageSizeRequest.region = Region.parse(obj.getJSONObject("region")); 17 | } 18 | if (obj.has("last_query_time")) { 19 | messageSizeRequest.last_query_time = obj.getLong("last_query_time"); 20 | } 21 | return messageSizeRequest; 22 | } 23 | 24 | public static JSONObject toJson(double lat, double longi, int precision, long ts) throws JSONException { 25 | JSONObject messageSizeRequest = new JSONObject(); 26 | messageSizeRequest.put("region", Region.toJson(lat, longi, precision)); 27 | messageSizeRequest.put("last_query_time", ts); 28 | return messageSizeRequest; 29 | } 30 | 31 | public static String toHttpString(double lat, double longi, int precision, long ts) { 32 | return NetworkConstant.BASE_URL+"Messages/List/"+String.format("?lat=%f&lon=%f&precision=%d&lastTimestamp=%d&api-version=%s",lat,longi,precision,ts,NetworkConstant.API_VERSION); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/MessageSizeResponse.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | public class MessageSizeResponse { 7 | 8 | public int sizeOfQueryResponse; 9 | 10 | public static MessageSizeResponse parse(JSONObject obj) throws JSONException { 11 | MessageSizeResponse response = new MessageSizeResponse(); 12 | if (obj.has("sizeOfQueryResponse")) { 13 | response.sizeOfQueryResponse = obj.getInt("sizeOfQueryResponse"); 14 | } 15 | return response; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/Region.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | public class Region { 7 | double latitudePrefix; 8 | double longitudePrefix; 9 | int precision; 10 | 11 | public static Region parse(JSONObject obj) throws JSONException { 12 | Region region = new Region(); 13 | if (obj.has("latitudePrefix")) { 14 | region.latitudePrefix = obj.getDouble("latitudePrefix"); 15 | } 16 | if (obj.has("longitudePrefix")) { 17 | region.longitudePrefix = obj.getDouble("longitudePrefix"); 18 | } 19 | if (obj.has("precision")) { 20 | region.precision = obj.getInt("precision"); 21 | } 22 | return region; 23 | } 24 | 25 | public static JSONObject toJson(double lat, double longi, double precision) throws JSONException { 26 | JSONObject region = new JSONObject(); 27 | region.put("latitudePrefix", lat); 28 | region.put("longitudePrefix", longi); 29 | region.put("precision", precision); 30 | return region; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/SelfReportRequest.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONArray; 4 | import org.json.JSONException; 5 | import org.json.JSONObject; 6 | 7 | import edu.uw.covidsafe.comms.NetworkConstant; 8 | 9 | public class SelfReportRequest { 10 | BlueToothSeed[] seeds; 11 | Region region; 12 | 13 | public static JSONObject toJson(String[] seeds, long[] ts_start, long[] ts_end, double lat, double longi, int precision) throws JSONException { 14 | JSONObject obj = new JSONObject(); 15 | JSONArray arr = new JSONArray(); 16 | for (int i = 0; i < seeds.length; i++) { 17 | arr.put(BlueToothSeed.toJson(seeds[i],ts_start[i],ts_end[i])); 18 | } 19 | obj.put("seeds",arr); 20 | obj.put("region",Region.toJson(lat,longi,precision)); 21 | return obj; 22 | } 23 | 24 | public static String toHttpString() { 25 | return NetworkConstant.BASE_URL+"Messages/SeedReport?api-version="+NetworkConstant.API_VERSION; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/json/Status.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.json; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | public class Status { 7 | int status_code; 8 | String status_message; 9 | 10 | public static Status parse(JSONObject obj) throws JSONException { 11 | Status status = new Status(); 12 | if (obj.has("status_code")) { 13 | status.status_code = obj.getInt("status_code"); 14 | } 15 | if (obj.has("status_message")) { 16 | status.status_message = obj.getString("status_message"); 17 | } 18 | return status; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/models/LatLng.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.models; 2 | 3 | public class LatLng { 4 | 5 | public double getLatitude() { 6 | return latitude; 7 | } 8 | 9 | public double getLongitude() { 10 | return longitude; 11 | } 12 | 13 | private double latitude; 14 | private double longitude; 15 | public LatLng(double latitude, double longitude){ 16 | this.latitude = latitude; 17 | this.longitude = longitude; 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/seed_uuid/SeedUUIDDbRecordDao.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.seed_uuid; 2 | 3 | import androidx.room.Dao; 4 | import androidx.room.Insert; 5 | import androidx.room.OnConflictStrategy; 6 | import androidx.room.Query; 7 | 8 | import java.util.List; 9 | 10 | @Dao 11 | public interface SeedUUIDDbRecordDao { 12 | 13 | @Query("SELECT * FROM seed_uuid_record_table") 14 | List getAllRecords(); 15 | 16 | // allowing the insert of the same word multiple times by passing a 17 | // conflict resolution strategy 18 | @Insert(onConflict = OnConflictStrategy.REPLACE) 19 | void insert(SeedUUIDRecord record); 20 | 21 | @Query("DELETE FROM seed_uuid_record_table") 22 | void deleteAll(); 23 | 24 | @Query("SELECT * FROM seed_uuid_record_table ORDER BY ts DESC") 25 | List getSortedRecordsByTimestamp(); 26 | 27 | @Query("SELECT * FROM seed_uuid_record_table WHERE ts BETWEEN :ts1 AND :ts2 LIMIT 1") 28 | SeedUUIDRecord getRecordBetween(long ts1, long ts2); 29 | 30 | @Query("DELETE FROM seed_uuid_record_table WHERE ts <= :ts_thresh") 31 | void deleteEarlierThan(long ts_thresh); 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/seed_uuid/SeedUUIDDbRecordRepository.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.seed_uuid; 2 | 3 | import android.content.Context; 4 | 5 | import java.util.List; 6 | 7 | public class SeedUUIDDbRecordRepository { 8 | private SeedUUIDDbRecordDao mRecordDao; 9 | 10 | // Note that in order to unit test the WordRepository, you have to remove the Application 11 | // dependency. This adds complexity and much more code, and this sample is not about testing. 12 | // See the BasicSample in the android-architecture-components repository at 13 | // https://github.com/googlesamples 14 | public SeedUUIDDbRecordRepository(Context application) { 15 | SeedUUIDDbRecordRoomDatabase db = SeedUUIDDbRecordRoomDatabase.getDatabase(application); 16 | mRecordDao = db.recordDao(); 17 | } 18 | 19 | // Room executes all queries on a separate thread. 20 | // Observed LiveData will notify the observer when the data has changed. 21 | public List getAllRecords() { 22 | return mRecordDao.getAllRecords(); 23 | } 24 | 25 | public List getAllSortedRecords() { 26 | return mRecordDao.getSortedRecordsByTimestamp(); 27 | } 28 | 29 | public SeedUUIDRecord getRecordBetween(long ts1, long ts2) { 30 | return mRecordDao.getRecordBetween(ts1, ts2); 31 | } 32 | 33 | // You must call this on a non-UI thread or your app will throw an exception. Room ensures 34 | // that you're not doing any long running operations on the main thread, blocking the UI. 35 | public void insert(SeedUUIDRecord record) { 36 | SeedUUIDDbRecordRoomDatabase.databaseWriteExecutor.execute(() -> { 37 | mRecordDao.insert(record); 38 | }); 39 | } 40 | 41 | public void deleteEarlierThan(long ts_thresh) { 42 | mRecordDao.deleteEarlierThan(ts_thresh); 43 | } 44 | 45 | public void deleteAll() { 46 | mRecordDao.deleteAll(); 47 | } 48 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/seed_uuid/SeedUUIDDbRecordRoomDatabase.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.seed_uuid; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.room.Database; 7 | import androidx.room.Room; 8 | import androidx.room.RoomDatabase; 9 | import androidx.sqlite.db.SupportSQLiteDatabase; 10 | 11 | import java.util.concurrent.ExecutorService; 12 | import java.util.concurrent.Executors; 13 | 14 | @Database(entities = {SeedUUIDRecord.class}, version = 1, exportSchema = false) 15 | public abstract class SeedUUIDDbRecordRoomDatabase extends RoomDatabase { 16 | 17 | private static final int NUMBER_OF_THREADS = 4; 18 | static final ExecutorService databaseWriteExecutor = 19 | Executors.newFixedThreadPool(NUMBER_OF_THREADS); 20 | private static volatile SeedUUIDDbRecordRoomDatabase INSTANCE; 21 | private static RoomDatabase.Callback sRoomDatabaseCallback = new RoomDatabase.Callback() { 22 | @Override 23 | public void onOpen(@NonNull SupportSQLiteDatabase db) { 24 | super.onOpen(db); 25 | 26 | // If you want to keep data through app restarts, 27 | // comment out the following block 28 | // databaseWriteExecutor.execute(() -> { 29 | // // Populate the database in the background. 30 | // // If you want to start with more words, just add them. 31 | // RecordDao dao = INSTANCE.recordDao(); 32 | // dao.deleteAll(); 33 | 34 | // Record word = new Record(System.currentTimeMillis(), 0.04f, false); 35 | // dao.insert(word); 36 | // }); 37 | } 38 | }; 39 | 40 | static SeedUUIDDbRecordRoomDatabase getDatabase(final Context context) { 41 | if (INSTANCE == null) { 42 | synchronized (SeedUUIDDbRecordRoomDatabase.class) { 43 | if (INSTANCE == null) { 44 | INSTANCE = Room.databaseBuilder(context, 45 | SeedUUIDDbRecordRoomDatabase.class, "seed_uuid_record_table") 46 | .build(); 47 | } 48 | } 49 | } 50 | 51 | return INSTANCE; 52 | } 53 | 54 | public abstract SeedUUIDDbRecordDao recordDao(); 55 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/seed_uuid/UUIDGeneratorTask.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.seed_uuid; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.util.Log; 6 | 7 | import com.example.covidsafe.R; 8 | 9 | import java.util.UUID; 10 | 11 | import edu.uw.covidsafe.ble.BluetoothUtils; 12 | import edu.uw.covidsafe.utils.Constants; 13 | import edu.uw.covidsafe.utils.CryptoUtils; 14 | 15 | public class UUIDGeneratorTask implements Runnable { 16 | 17 | Context context; 18 | 19 | public UUIDGeneratorTask(Context context) { 20 | this.context = context; 21 | } 22 | 23 | @Override 24 | public void run() { 25 | if (Constants.EnableUUIDGeneration) { 26 | Log.e("crypto","generate uuid"); 27 | // get the most recently generated seed 28 | SharedPreferences prefs = context.getSharedPreferences(Constants.SHARED_PREFENCE_NAME, Context.MODE_PRIVATE); 29 | long mostRecentSeedTimestamp = prefs.getLong(context.getString(R.string.most_recent_seed_timestamp_pkey), 0); 30 | 31 | Log.e("crypto","most recent seed timestamp "+mostRecentSeedTimestamp); 32 | UUID uuid = CryptoUtils.generateSeedHelperWithMostRecent(context, mostRecentSeedTimestamp); 33 | 34 | Log.e("ble", "changing contact uuid now"); 35 | if (uuid != null) { 36 | Log.e("ble", "changing contact uuid now to " + uuid.toString()); 37 | Constants.contactUUID = UUID.fromString(uuid.toString()); 38 | } 39 | 40 | Log.e("ble", "can we broadcast?" + (Constants.blueAdapter != null)); 41 | if (Constants.blueAdapter != null) { 42 | Log.e("ble", "is advertiser null?" + (Constants.blueAdapter.getBluetoothLeAdvertiser() == null)); 43 | } 44 | if (Constants.blueAdapter != null && Constants.blueAdapter.getBluetoothLeAdvertiser() != null) { 45 | Log.e("ble", "about to stop advertising"); 46 | Constants.blueAdapter.getBluetoothLeAdvertiser().stopAdvertising(BluetoothUtils.advertiseCallback); 47 | //restart beacon after UUID generation 48 | Log.e("ble", "about to mkbeacon"); 49 | BluetoothUtils.mkBeacon(context); 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/Splash.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | 7 | import androidx.appcompat.app.AppCompatActivity; 8 | 9 | import com.example.covidsafe.R; 10 | 11 | import edu.uw.covidsafe.ui.onboarding.OnboardingActivity; 12 | import edu.uw.covidsafe.utils.Constants; 13 | 14 | public class Splash extends AppCompatActivity { 15 | 16 | @Override 17 | public void onCreate(Bundle icicle) { 18 | super.onCreate(icicle); 19 | // 20 | setContentView(R.layout.splash); 21 | 22 | getSupportActionBar().hide(); 23 | 24 | new Handler().postDelayed(new Runnable(){ 25 | @Override 26 | public void run() { 27 | Intent mainIntent = new Intent(Splash.this, OnboardingActivity.class); 28 | Splash.this.startActivity(mainIntent); 29 | Splash.this.finish(); 30 | } 31 | }, Constants.SPLASH_DISPLAY_LENGTH); 32 | // 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/contact_log/ContactLogPageAdapter.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.contact_log; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | import androidx.fragment.app.Fragment; 8 | import androidx.fragment.app.FragmentManager; 9 | import androidx.fragment.app.FragmentPagerAdapter; 10 | 11 | import com.example.covidsafe.R; 12 | 13 | import edu.uw.covidsafe.utils.Constants; 14 | 15 | public class ContactLogPageAdapter extends FragmentPagerAdapter { 16 | Context cxt; 17 | public ContactLogPageAdapter(@NonNull FragmentManager fm, Context cxt) { 18 | super(fm); 19 | this.cxt = cxt; 20 | } 21 | 22 | @NonNull 23 | @Override 24 | public Fragment getItem(int position) { 25 | if (position == 0) { 26 | return Constants.LocationFragment; 27 | } 28 | else if (position == 1) { 29 | return Constants.PeopleFragment; 30 | } 31 | return null; 32 | } 33 | 34 | @Override 35 | public int getCount() { 36 | return 2; 37 | } 38 | 39 | @Nullable 40 | @Override 41 | public CharSequence getPageTitle(int position) { 42 | if (position == 0) { 43 | return cxt.getString(R.string.locations_text); 44 | } 45 | else if (position == 1) { 46 | return cxt.getString(R.string.people_text); 47 | } 48 | return ""; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/contact_trace/ContactPageAdapter.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.contact_trace; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | 7 | import androidx.annotation.NonNull; 8 | import androidx.annotation.Nullable; 9 | import androidx.fragment.app.Fragment; 10 | import androidx.fragment.app.FragmentManager; 11 | import androidx.fragment.app.FragmentPagerAdapter; 12 | 13 | import com.example.covidsafe.R; 14 | 15 | public class ContactPageAdapter extends FragmentPagerAdapter { 16 | Context cxt; 17 | public ContactPageAdapter(@NonNull FragmentManager fm, Context cxt) { 18 | super(fm); 19 | this.cxt = cxt; 20 | } 21 | 22 | @NonNull 23 | @Override 24 | public Fragment getItem(int position) { 25 | Log.e("state","contact page adapter "+position); 26 | ContactStepFragment frag = new ContactStepFragment(); 27 | Bundle bundle = new Bundle(); 28 | bundle.putInt("pgnum", position); 29 | if (position == 0) { 30 | } 31 | else if (position == 1) { 32 | bundle.putInt("image", R.drawable.clipboard); 33 | } 34 | else if (position == 2) { 35 | bundle.putInt("image", R.drawable.map_header); 36 | } 37 | else if (position == 3) { 38 | bundle.putInt("image", R.drawable.person); 39 | } 40 | else if (position == 4) { 41 | bundle.putInt("image", R.drawable.speech_icon); 42 | } 43 | frag.setArguments(bundle); 44 | return frag; 45 | } 46 | 47 | @Override 48 | public int getCount() { 49 | return 5; 50 | } 51 | 52 | @Nullable 53 | @Override 54 | public CharSequence getPageTitle(int position) { 55 | return cxt.getString(R.string.inter_prep); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/contact_trace/HumanDbModel.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.contact_trace; 2 | 3 | import android.app.Application; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.lifecycle.AndroidViewModel; 7 | import androidx.lifecycle.LiveData; 8 | 9 | import java.util.List; 10 | 11 | public class HumanDbModel extends AndroidViewModel { 12 | HumanDbRecordRepository repo; 13 | public LiveData> records; 14 | public HumanDbModel(@NonNull Application application) { 15 | super(application); 16 | repo = new HumanDbRecordRepository(application); 17 | records = repo.getSortedRecords(); 18 | } 19 | 20 | public LiveData> getAllSorted() { 21 | return records; 22 | } 23 | 24 | public void deleteAll() {repo.deleteAll();} 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/contact_trace/HumanDbRecordDao.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.contact_trace; 2 | 3 | import androidx.lifecycle.LiveData; 4 | import androidx.room.Dao; 5 | import androidx.room.Insert; 6 | import androidx.room.OnConflictStrategy; 7 | import androidx.room.Query; 8 | 9 | import java.util.List; 10 | 11 | @Dao 12 | public interface HumanDbRecordDao { 13 | 14 | @Query("SELECT * FROM human_record_table") 15 | List getAllRecords(); 16 | 17 | // allowing the insert of the same word multiple times by passing a 18 | // conflict resolution strategy 19 | @Insert(onConflict = OnConflictStrategy.REPLACE) 20 | void insert(HumanRecord record); 21 | 22 | @Query("DELETE FROM human_record_table") 23 | void deleteAll(); 24 | 25 | @Query("DELETE FROM human_record_table WHERE name == :name") 26 | void delete(String name); 27 | 28 | @Query("SELECT * FROM human_record_table ORDER BY name") 29 | LiveData> getSortedRecords(); 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/contact_trace/HumanDbRecordRepository.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.contact_trace; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.lifecycle.LiveData; 6 | 7 | import java.util.List; 8 | 9 | public class HumanDbRecordRepository { 10 | private HumanDbRecordDao mRecordDao; 11 | 12 | // Note that in order to unit test the WordRepository, you have to remove the Application 13 | // dependency. This adds complexity and much more code, and this sample is not about testing. 14 | // See the BasicSample in the android-architecture-components repository at 15 | // https://github.com/googlesamples 16 | public HumanDbRecordRepository(Context application) { 17 | HumanDbRecordRoomDatabase db = HumanDbRecordRoomDatabase.getDatabase(application); 18 | mRecordDao = db.recordDao(); 19 | // mAllRecords = mRecordDao.getSortedRecords(); 20 | } 21 | 22 | // Room executes all queries on a separate thread. 23 | // Observed LiveData will notify the observer when the data has changed. 24 | public List getAllRecords() { 25 | return mRecordDao.getAllRecords(); 26 | } 27 | 28 | // You must call this on a non-UI thread or your app will throw an exception. Room ensures 29 | // that you're not doing any long running operations on the main thread, blocking the UI. 30 | public void insert(HumanRecord record) { 31 | HumanDbRecordRoomDatabase.databaseWriteExecutor.execute(() -> { 32 | mRecordDao.insert(record); 33 | }); 34 | } 35 | 36 | public void delete(String name) { 37 | mRecordDao.delete(name); 38 | } 39 | 40 | public LiveData> getSortedRecords() { 41 | return mRecordDao.getSortedRecords(); 42 | } 43 | 44 | public void deleteAll() { 45 | mRecordDao.deleteAll(); 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/contact_trace/HumanDbRecordRoomDatabase.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.contact_trace; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.room.Database; 7 | import androidx.room.Room; 8 | import androidx.room.RoomDatabase; 9 | import androidx.sqlite.db.SupportSQLiteDatabase; 10 | 11 | import java.util.concurrent.ExecutorService; 12 | import java.util.concurrent.Executors; 13 | 14 | @Database(entities = {HumanRecord.class}, version = 1, exportSchema = false) 15 | public abstract class HumanDbRecordRoomDatabase extends RoomDatabase { 16 | 17 | private static final int NUMBER_OF_THREADS = 4; 18 | static final ExecutorService databaseWriteExecutor = 19 | Executors.newFixedThreadPool(NUMBER_OF_THREADS); 20 | private static volatile HumanDbRecordRoomDatabase INSTANCE; 21 | private static RoomDatabase.Callback sRoomDatabaseCallback = new RoomDatabase.Callback() { 22 | @Override 23 | public void onOpen(@NonNull SupportSQLiteDatabase db) { 24 | super.onOpen(db); 25 | 26 | // If you want to keep data through app restarts, 27 | // comment out the following block 28 | // databaseWriteExecutor.execute(() -> { 29 | // // Populate the database in the background. 30 | // // If you want to start with more words, just add them. 31 | // RecordDao dao = INSTANCE.recordDao(); 32 | // dao.deleteAll(); 33 | 34 | // Record word = new Record(System.currentTimeMillis(), 0.04f, false); 35 | // dao.insert(word); 36 | // }); 37 | } 38 | }; 39 | 40 | static HumanDbRecordRoomDatabase getDatabase(final Context context) { 41 | if (INSTANCE == null) { 42 | synchronized (HumanDbRecordRoomDatabase.class) { 43 | if (INSTANCE == null) { 44 | INSTANCE = Room.databaseBuilder(context, 45 | HumanDbRecordRoomDatabase.class, "human_record_database") 46 | .build(); 47 | } 48 | } 49 | } 50 | 51 | return INSTANCE; 52 | } 53 | 54 | public abstract HumanDbRecordDao recordDao(); 55 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/contact_trace/HumanOpsAsyncTask.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.contact_trace; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | import android.util.Log; 6 | 7 | import edu.uw.covidsafe.utils.Constants; 8 | 9 | public class HumanOpsAsyncTask extends AsyncTask { 10 | private HumanDbRecordRepository repo; 11 | private HumanRecord result; 12 | private Constants.HumanDatabaseOps op; 13 | 14 | public HumanOpsAsyncTask(Context cxt, String phone, String name, String imageUri, String email) { 15 | repo = new HumanDbRecordRepository(cxt); 16 | this.result = new HumanRecord(phone, name, imageUri, email); 17 | this.op = Constants.HumanDatabaseOps.Insert; 18 | } 19 | 20 | public HumanOpsAsyncTask(Context cxt, Constants.HumanDatabaseOps op) { 21 | repo = new HumanDbRecordRepository(cxt); 22 | this.op = op; 23 | } 24 | 25 | public HumanOpsAsyncTask(Context cxt, Constants.HumanDatabaseOps op, HumanRecord record) { 26 | repo = new HumanDbRecordRepository(cxt); 27 | this.op = op; 28 | this.result = record; 29 | } 30 | 31 | @Override 32 | protected Void doInBackground(Void... params) { 33 | Log.e("human","doinbackground human "+this.op); 34 | if (this.op == Constants.HumanDatabaseOps.Insert) { 35 | repo.insert(this.result); 36 | } 37 | else if (this.op == Constants.HumanDatabaseOps.Delete) { 38 | repo.delete(this.result.getName()); 39 | } 40 | else if (this.op == Constants.HumanDatabaseOps.DeleteAll) { 41 | repo.deleteAll(); 42 | } 43 | return null; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/contact_trace/HumanRecord.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.contact_trace; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.room.ColumnInfo; 5 | import androidx.room.Entity; 6 | import androidx.room.PrimaryKey; 7 | 8 | @Entity(tableName = "human_record_table") 9 | public class HumanRecord { 10 | 11 | @PrimaryKey 12 | @NonNull 13 | @ColumnInfo(name = "name") 14 | private String name; 15 | 16 | @ColumnInfo(name = "phoneNumber") 17 | private String phoneNumber; 18 | 19 | public String getEmail() { 20 | return email; 21 | } 22 | 23 | public void setEmail(String email) { 24 | this.email = email; 25 | } 26 | 27 | @ColumnInfo(name = "email") 28 | private String email; 29 | 30 | @NonNull 31 | public String getImgUri() { 32 | return imgUri; 33 | } 34 | 35 | public void setImgUri(@NonNull String imgUri) { 36 | this.imgUri = imgUri; 37 | } 38 | 39 | @ColumnInfo(name = "imgUri") 40 | private String imgUri; 41 | 42 | @NonNull 43 | public String getName() { 44 | return name; 45 | } 46 | 47 | public void setName(@NonNull String name) { 48 | this.name = name; 49 | } 50 | 51 | @NonNull 52 | public String getPhoneNumber() { 53 | return phoneNumber; 54 | } 55 | 56 | public void setPhoneNumber(@NonNull String phoneNumber) { 57 | this.phoneNumber = phoneNumber; 58 | } 59 | 60 | public HumanRecord(@NonNull String phoneNumber, String name, String imgUri, String email) { 61 | this.phoneNumber = phoneNumber; 62 | this.name = name; 63 | this.imgUri = imgUri; 64 | this.email = email; 65 | } 66 | 67 | public String toString() { 68 | return this.name + " ("+this.phoneNumber+")\n"; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/contact_trace/NonSwipeableViewPager.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.contact_trace; 2 | import android.content.Context; 3 | import android.util.AttributeSet; 4 | import android.view.MotionEvent; 5 | import android.view.animation.DecelerateInterpolator; 6 | import android.widget.Scroller; 7 | 8 | import androidx.viewpager.widget.ViewPager; 9 | 10 | import java.lang.reflect.Field; 11 | 12 | public class NonSwipeableViewPager extends ViewPager { 13 | 14 | public NonSwipeableViewPager(Context context) { 15 | super(context); 16 | setMyScroller(); 17 | } 18 | 19 | public NonSwipeableViewPager(Context context, AttributeSet attrs) { 20 | super(context, attrs); 21 | setMyScroller(); 22 | } 23 | 24 | @Override 25 | public boolean onInterceptTouchEvent(MotionEvent event) { 26 | // Never allow swiping to switch between pages 27 | return false; 28 | } 29 | 30 | @Override 31 | public boolean onTouchEvent(MotionEvent event) { 32 | // Never allow swiping to switch between pages 33 | return false; 34 | } 35 | 36 | //down one is added for smooth scrolling 37 | 38 | private void setMyScroller() { 39 | try { 40 | Class viewpager = ViewPager.class; 41 | Field scroller = viewpager.getDeclaredField("mScroller"); 42 | scroller.setAccessible(true); 43 | scroller.set(this, new MyScroller(getContext())); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } 47 | } 48 | 49 | public class MyScroller extends Scroller { 50 | public MyScroller(Context context) { 51 | super(context, new DecelerateInterpolator()); 52 | } 53 | 54 | @Override 55 | public void startScroll(int startX, int startY, int dx, int dy, int duration) { 56 | super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/health/HealthPageAdapter.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.health; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.Nullable; 7 | import androidx.fragment.app.Fragment; 8 | import androidx.fragment.app.FragmentManager; 9 | import androidx.fragment.app.FragmentPagerAdapter; 10 | 11 | import com.example.covidsafe.R; 12 | 13 | import edu.uw.covidsafe.utils.Constants; 14 | 15 | public class HealthPageAdapter extends FragmentPagerAdapter { 16 | Context cxt; 17 | public HealthPageAdapter(@NonNull FragmentManager fm, Context cxt) { 18 | super(fm); 19 | this.cxt = cxt; 20 | } 21 | 22 | @NonNull 23 | @Override 24 | public Fragment getItem(int position) { 25 | if (position == 0) { 26 | return Constants.SymptomTrackerFragment; 27 | } 28 | else if (position == 1) { 29 | return Constants.DiagnosisFragment; 30 | } 31 | return null; 32 | } 33 | 34 | @Override 35 | public int getCount() { 36 | return 2; 37 | } 38 | 39 | @Nullable 40 | @Override 41 | public CharSequence getPageTitle(int position) { 42 | if (position == 0) { 43 | return cxt.getString(R.string.symptoms_text); 44 | } 45 | else if (position == 1) { 46 | return cxt.getString(R.string.diagnosis_text); 47 | } 48 | return ""; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/notif/NotifDbModel.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.notif; 2 | 3 | import android.app.Application; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.lifecycle.AndroidViewModel; 7 | import androidx.lifecycle.LiveData; 8 | 9 | import java.util.List; 10 | 11 | public class NotifDbModel extends AndroidViewModel { 12 | NotifDbRecordRepository repo; 13 | public LiveData> records; 14 | public NotifDbModel(@NonNull Application application) { 15 | super(application); 16 | repo = new NotifDbRecordRepository(application); 17 | records = repo.getSortedRecords(); 18 | } 19 | 20 | public LiveData> getAllSorted() { 21 | return records; 22 | } 23 | 24 | public void deleteAll() {repo.deleteAll();} 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/notif/NotifDbRecordDao.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.notif; 2 | 3 | import androidx.lifecycle.LiveData; 4 | import androidx.room.Dao; 5 | import androidx.room.Insert; 6 | import androidx.room.OnConflictStrategy; 7 | import androidx.room.Query; 8 | 9 | import java.util.List; 10 | 11 | @Dao 12 | public interface NotifDbRecordDao { 13 | 14 | @Query("SELECT * from notif_record_table") 15 | List getAllRecords(); 16 | 17 | // allowing the insert of the same word multiple times by passing a 18 | // conflict resolution strategy 19 | @Insert(onConflict = OnConflictStrategy.REPLACE) 20 | void insert(NotifRecord record); 21 | 22 | @Query("DELETE FROM notif_record_table") 23 | void deleteAll(); 24 | 25 | @Query("DELETE FROM notif_record_table WHERE ts_start <= :ts_thresh") 26 | void deleteEarlierThan(long ts_thresh); 27 | 28 | @Query("SELECT * from notif_record_table ORDER BY ts_start DESC LIMIT 5") 29 | LiveData> getSortedRecords(); 30 | 31 | @Query("SELECT * from notif_record_table WHERE ts_start BETWEEN :ts1 AND :ts2") 32 | List getRecordsBetweenTimestamp(long ts1, long ts2); 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/notif/NotifDbRecordRepository.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.notif; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.lifecycle.LiveData; 6 | 7 | import java.util.List; 8 | 9 | public class NotifDbRecordRepository { 10 | private NotifDbRecordDao mRecordDao; 11 | 12 | // Note that in order to unit test the WordRepository, you have to remove the Application 13 | // dependency. This adds complexity and much more code, and this sample is not about testing. 14 | // See the BasicSample in the android-architecture-components repository at 15 | // https://github.com/googlesamples 16 | public NotifDbRecordRepository(Context application) { 17 | NotifDbRecordRoomDatabase db = NotifDbRecordRoomDatabase.getDatabase(application); 18 | mRecordDao = db.recordDao(); 19 | } 20 | 21 | // Room executes all queries on a separate thread. 22 | // Observed LiveData will notify the observer when the data has changed. 23 | public List getAllRecords() { 24 | return mRecordDao.getAllRecords(); 25 | } 26 | 27 | // Room executes all queries on a separate thread. 28 | // Observed LiveData will notify the observer when the data has changed. 29 | public LiveData> getSortedRecords() { 30 | return mRecordDao.getSortedRecords(); 31 | } 32 | 33 | public List getRecordsBetweenTimestamps(long ts1, long ts2) { 34 | return mRecordDao.getRecordsBetweenTimestamp(ts1, ts2); 35 | } 36 | 37 | // You must call this on a non-UI thread or your app will throw an exception. Room ensures 38 | // that you're not doing any long running operations on the main thread, blocking the UI. 39 | public void insert(NotifRecord record) { 40 | NotifDbRecordRoomDatabase.databaseWriteExecutor.execute(() -> { 41 | mRecordDao.insert(record); 42 | }); 43 | } 44 | 45 | public void deleteAll() { 46 | mRecordDao.deleteAll(); 47 | } 48 | 49 | public void deleteEarlierThan(long ts_thresh) { 50 | mRecordDao.deleteEarlierThan(ts_thresh); 51 | } 52 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/notif/NotifDbRecordRoomDatabase.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.notif; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.room.Database; 7 | import androidx.room.Room; 8 | import androidx.room.RoomDatabase; 9 | import androidx.sqlite.db.SupportSQLiteDatabase; 10 | 11 | import java.util.concurrent.ExecutorService; 12 | import java.util.concurrent.Executors; 13 | 14 | @Database(entities = {NotifRecord.class}, version = 1, exportSchema = false) 15 | public abstract class NotifDbRecordRoomDatabase extends RoomDatabase { 16 | 17 | private static final int NUMBER_OF_THREADS = 4; 18 | static final ExecutorService databaseWriteExecutor = 19 | Executors.newFixedThreadPool(NUMBER_OF_THREADS); 20 | private static volatile NotifDbRecordRoomDatabase INSTANCE; 21 | private static RoomDatabase.Callback sRoomDatabaseCallback = new RoomDatabase.Callback() { 22 | @Override 23 | public void onOpen(@NonNull SupportSQLiteDatabase db) { 24 | super.onOpen(db); 25 | 26 | // If you want to keep data through app restarts, 27 | // comment out the following block 28 | // databaseWriteExecutor.execute(() -> { 29 | // // Populate the database in the background. 30 | // // If you want to start with more words, just add them. 31 | // RecordDao dao = INSTANCE.recordDao(); 32 | // dao.deleteAll(); 33 | 34 | // Record word = new Record(System.currentTimeMillis(), 0.04f, false); 35 | // dao.insert(word); 36 | // }); 37 | } 38 | }; 39 | 40 | static NotifDbRecordRoomDatabase getDatabase(final Context context) { 41 | if (INSTANCE == null) { 42 | synchronized (NotifDbRecordRoomDatabase.class) { 43 | if (INSTANCE == null) { 44 | INSTANCE = Room.databaseBuilder(context, 45 | NotifDbRecordRoomDatabase.class, "notif_record_database") 46 | .build(); 47 | } 48 | } 49 | } 50 | 51 | return INSTANCE; 52 | } 53 | 54 | public abstract NotifDbRecordDao recordDao(); 55 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/notif/NotifOpsAsyncTask.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.notif; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | import android.util.Log; 6 | 7 | import java.util.List; 8 | 9 | import edu.uw.covidsafe.utils.Constants; 10 | 11 | public class NotifOpsAsyncTask extends AsyncTask { 12 | private NotifDbRecordRepository repo; 13 | private NotifRecord record; 14 | private Constants.NotifDatabaseOps op; 15 | 16 | public NotifOpsAsyncTask(Context context, NotifRecord rec) { 17 | repo = new NotifDbRecordRepository(context); 18 | this.record = new NotifRecord(rec.getTs_start(), rec.getTs_end(), rec.getMsg(), rec.getMsgType(), rec.current); 19 | this.op = Constants.NotifDatabaseOps.Insert; 20 | } 21 | 22 | public NotifOpsAsyncTask(Context context, Constants.NotifDatabaseOps op) { 23 | repo = new NotifDbRecordRepository(context); 24 | this.op = op; 25 | } 26 | 27 | @Override 28 | protected Void doInBackground(Void... params) { 29 | Log.e("notif","doinbackground notif "+this.op); 30 | if (this.op == Constants.NotifDatabaseOps.Insert) { 31 | repo.insert(this.record); 32 | // if (Constants.WRITE_TO_DISK) { 33 | // Utils.notifLogToFile(this.context, this.record); 34 | // } 35 | } 36 | else if (this.op == Constants.NotifDatabaseOps.ViewAll) { 37 | List records = repo.getAllRecords(); 38 | for (NotifRecord record : records) { 39 | Log.e("notif",record.toString()); 40 | } 41 | } 42 | else if (this.op == Constants.NotifDatabaseOps.DeleteAll) { 43 | Log.e("notif","delete all"); 44 | repo.deleteAll(); 45 | } 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/notif/NotifRecord.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.notif; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.room.ColumnInfo; 5 | import androidx.room.Entity; 6 | import androidx.room.PrimaryKey; 7 | 8 | @Entity(tableName = "notif_record_table") 9 | public class NotifRecord { 10 | 11 | @PrimaryKey 12 | @NonNull 13 | @ColumnInfo(name = "ts_start") 14 | public long ts_start; 15 | 16 | @ColumnInfo(name = "ts_end") 17 | public long ts_end; 18 | 19 | // exposure or narrowcast 20 | @NonNull 21 | @ColumnInfo(name = "msgType") 22 | public int msgType; 23 | 24 | // history or current 25 | @NonNull 26 | @ColumnInfo(name = "current") 27 | public boolean current; 28 | 29 | @NonNull 30 | @ColumnInfo(name = "msg") 31 | public String msg; 32 | 33 | public NotifRecord(@NonNull long ts_start, long ts_end, String msg, int msgType, boolean current) { 34 | this.ts_start = ts_start; 35 | this.ts_end = ts_end; 36 | this.msg = msg; 37 | this.msgType = msgType; 38 | this.current = current; 39 | } 40 | 41 | public long getTs_start() { 42 | return this.ts_start; 43 | } 44 | 45 | public long getTs_end() { 46 | return this.ts_end; 47 | } 48 | 49 | public String getMsg() { return this.msg; } 50 | 51 | public int getMsgType() { return this.msgType; } 52 | 53 | public boolean getCurrent() { return this.current; } 54 | 55 | public String toString() { 56 | return this.ts_start+","+this.ts_end+","+this.msg+","+this.msgType; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/onboarding/OnboardingStateAdapter.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.onboarding; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.fragment.app.Fragment; 7 | import androidx.fragment.app.FragmentManager; 8 | import androidx.fragment.app.FragmentPagerAdapter; 9 | 10 | import com.example.covidsafe.R; 11 | 12 | import edu.uw.covidsafe.utils.Constants; 13 | 14 | public class OnboardingStateAdapter extends FragmentPagerAdapter { 15 | 16 | public OnboardingStateAdapter(@NonNull FragmentManager fm) { 17 | super(fm); 18 | } 19 | 20 | @NonNull 21 | @Override 22 | public Fragment getItem(int position) { 23 | StoryFragment frag = new StoryFragment(); 24 | Bundle bundle = new Bundle(); 25 | // Log.e("STATE","page number "+position); 26 | Constants.pageNumber = position; 27 | if (position==0) { 28 | bundle.putInt("image", R.drawable.onboard1); 29 | bundle.putInt("message", R.string.story1); 30 | bundle.putInt("title", R.string.storyTitle1); 31 | } 32 | else if (position==1) { 33 | bundle.putInt("image", R.drawable.onboard2); 34 | bundle.putInt("message", R.string.story2); 35 | bundle.putInt("title", R.string.storyTitle2); 36 | } 37 | else if (position==2) { 38 | bundle.putInt("image", R.drawable.onboard3); 39 | bundle.putInt("message", R.string.story3); 40 | bundle.putInt("title", R.string.storyTitle3); 41 | } 42 | else if (position==3) { 43 | bundle.putInt("image", R.drawable.onboard4); 44 | bundle.putInt("message", R.string.story4); 45 | bundle.putInt("title", R.string.storyTitle4); 46 | } 47 | bundle.putInt("pos",position); 48 | frag.setArguments(bundle); 49 | return frag; 50 | } 51 | 52 | @Override 53 | public int getCount() { 54 | return 5; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/symptoms/SymptomDbModel.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.symptoms; 2 | 3 | import android.app.Application; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.lifecycle.AndroidViewModel; 7 | import androidx.lifecycle.LiveData; 8 | 9 | import java.util.List; 10 | 11 | public class SymptomDbModel extends AndroidViewModel { 12 | SymptomsDbRecordRepository repo; 13 | public LiveData> records; 14 | public SymptomDbModel(@NonNull Application application) { 15 | super(application); 16 | repo = new SymptomsDbRecordRepository(application); 17 | records = repo.getSortedRecords(); 18 | } 19 | 20 | public LiveData> getAllSorted() { 21 | return records; 22 | } 23 | 24 | public void deleteAll() {repo.deleteAll();} 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/symptoms/SymptomsDbRecordDao.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.symptoms; 2 | 3 | import androidx.lifecycle.LiveData; 4 | import androidx.room.Dao; 5 | import androidx.room.Insert; 6 | import androidx.room.OnConflictStrategy; 7 | import androidx.room.Query; 8 | 9 | import java.util.List; 10 | 11 | @Dao 12 | public interface SymptomsDbRecordDao { 13 | 14 | @Query("SELECT * FROM symptoms_record_table") 15 | List getAllRecords(); 16 | 17 | // allowing the insert of the same word multiple times by passing a 18 | // conflict resolution strategy 19 | @Insert(onConflict = OnConflictStrategy.REPLACE) 20 | void insert(SymptomsRecord record); 21 | 22 | @Query("DELETE FROM symptoms_record_table") 23 | void deleteAll(); 24 | 25 | @Query("DELETE FROM symptoms_record_table WHERE ts == :ts") 26 | void delete(long ts); 27 | 28 | @Query("DELETE FROM symptoms_record_table WHERE ts <= :ts_thresh") 29 | void deleteEarlierThan(long ts_thresh); 30 | 31 | @Query("SELECT * FROM symptoms_record_table ORDER BY ts DESC") 32 | LiveData> getSortedRecordsByTimestamp(); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/symptoms/SymptomsDbRecordRepository.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.symptoms; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.lifecycle.LiveData; 6 | 7 | import java.util.List; 8 | 9 | public class SymptomsDbRecordRepository { 10 | private SymptomsDbRecordDao mRecordDao; 11 | 12 | // Note that in order to unit test the WordRepository, you have to remove the Application 13 | // dependency. This adds complexity and much more code, and this sample is not about testing. 14 | // See the BasicSample in the android-architecture-components repository at 15 | // https://github.com/googlesamples 16 | public SymptomsDbRecordRepository(Context application) { 17 | SymptomsDbRecordRoomDatabase db = SymptomsDbRecordRoomDatabase.getDatabase(application); 18 | mRecordDao = db.recordDao(); 19 | // mAllRecords = mRecordDao.getSortedRecords(); 20 | } 21 | 22 | // Room executes all queries on a separate thread. 23 | // Observed LiveData will notify the observer when the data has changed. 24 | 25 | public LiveData> getSortedRecords() { 26 | return mRecordDao.getSortedRecordsByTimestamp(); 27 | } 28 | 29 | // You must call this on a non-UI thread or your app will throw an exception. Room ensures 30 | // that you're not doing any long running operations on the main thread, blocking the UI. 31 | public void insert(SymptomsRecord record) { 32 | SymptomsDbRecordRoomDatabase.databaseWriteExecutor.execute(() -> { 33 | mRecordDao.insert(record); 34 | }); 35 | } 36 | 37 | public void deleteAll() { 38 | mRecordDao.deleteAll(); 39 | } 40 | 41 | public void delete(long ts) { 42 | mRecordDao.delete(ts); 43 | } 44 | 45 | public void deleteEarlierThan(long ts_thresh) { 46 | mRecordDao.deleteEarlierThan(ts_thresh); 47 | } 48 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/symptoms/SymptomsDbRecordRoomDatabase.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.symptoms; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.room.Database; 7 | import androidx.room.Room; 8 | import androidx.room.RoomDatabase; 9 | import androidx.sqlite.db.SupportSQLiteDatabase; 10 | 11 | import java.util.concurrent.ExecutorService; 12 | import java.util.concurrent.Executors; 13 | 14 | @Database(entities = {SymptomsRecord.class}, version = 1, exportSchema = false) 15 | public abstract class SymptomsDbRecordRoomDatabase extends RoomDatabase { 16 | 17 | private static final int NUMBER_OF_THREADS = 4; 18 | static final ExecutorService databaseWriteExecutor = 19 | Executors.newFixedThreadPool(NUMBER_OF_THREADS); 20 | private static volatile SymptomsDbRecordRoomDatabase INSTANCE; 21 | private static RoomDatabase.Callback sRoomDatabaseCallback = new RoomDatabase.Callback() { 22 | @Override 23 | public void onOpen(@NonNull SupportSQLiteDatabase db) { 24 | super.onOpen(db); 25 | 26 | // If you want to keep data through app restarts, 27 | // comment out the following block 28 | // databaseWriteExecutor.execute(() -> { 29 | // // Populate the database in the background. 30 | // // If you want to start with more words, just add them. 31 | // RecordDao dao = INSTANCE.recordDao(); 32 | // dao.deleteAll(); 33 | 34 | // Record word = new Record(System.currentTimeMillis(), 0.04f, false); 35 | // dao.insert(word); 36 | // }); 37 | } 38 | }; 39 | 40 | static SymptomsDbRecordRoomDatabase getDatabase(final Context context) { 41 | if (INSTANCE == null) { 42 | synchronized (SymptomsDbRecordRoomDatabase.class) { 43 | if (INSTANCE == null) { 44 | INSTANCE = Room.databaseBuilder(context, 45 | SymptomsDbRecordRoomDatabase.class, "symptoms_record_database") 46 | .build(); 47 | } 48 | } 49 | } 50 | 51 | return INSTANCE; 52 | } 53 | 54 | public abstract SymptomsDbRecordDao recordDao(); 55 | } -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/ui/symptoms/SymptomsOpsAsyncTask.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.ui.symptoms; 2 | 3 | import android.content.Context; 4 | import android.os.AsyncTask; 5 | import android.util.Log; 6 | 7 | import edu.uw.covidsafe.utils.Constants; 8 | 9 | public class SymptomsOpsAsyncTask extends AsyncTask { 10 | private SymptomsDbRecordRepository repo; 11 | private SymptomsRecord result; 12 | private Constants.SymptomsDatabaseOps op; 13 | 14 | public SymptomsOpsAsyncTask(Context context, SymptomsRecord result) { 15 | repo = new SymptomsDbRecordRepository(context); 16 | this.result = result; 17 | this.op = Constants.SymptomsDatabaseOps.Insert; 18 | } 19 | 20 | public SymptomsOpsAsyncTask(Constants.SymptomsDatabaseOps op, Context cxt) { 21 | repo = new SymptomsDbRecordRepository(cxt); 22 | this.op = op; 23 | } 24 | 25 | public SymptomsOpsAsyncTask(Constants.SymptomsDatabaseOps op, Context cxt, SymptomsRecord record) { 26 | repo = new SymptomsDbRecordRepository(cxt); 27 | this.op = op; 28 | this.result = record; 29 | } 30 | 31 | @Override 32 | protected Void doInBackground(Void... params) { 33 | Log.e("ble","doinbackground symptoms "+this.op); 34 | if (this.op == Constants.SymptomsDatabaseOps.Insert) { 35 | repo.insert(this.result); 36 | // if (Constants.WRITE_TO_DISK) { 37 | // Utils.symptomsLogToFile(this.context, this.result); 38 | // } 39 | } 40 | else if (this.op == Constants.SymptomsDatabaseOps.DeleteAll) { 41 | repo.deleteAll(); 42 | } 43 | else if (this.op == Constants.SymptomsDatabaseOps.Delete) { 44 | repo.delete(this.result.getTs()); 45 | } 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/edu/uw/covidsafe/workmanager/workers/BluetoothScanWorker.java: -------------------------------------------------------------------------------- 1 | package edu.uw.covidsafe.workmanager.workers; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.work.Data; 7 | import androidx.work.Worker; 8 | import androidx.work.WorkerParameters; 9 | 10 | public class BluetoothScanWorker extends Worker { 11 | 12 | private Context context; 13 | private WorkerParameters workerParameters; 14 | private Data.Builder resultData; 15 | public static final String STATUS = "status"; 16 | 17 | public BluetoothScanWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { 18 | super(context, workerParams); 19 | this.context = context; 20 | this.workerParameters = workerParams; 21 | resultData = new Data.Builder(); 22 | } 23 | 24 | @NonNull 25 | @Override 26 | public Result doWork() { 27 | return null; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/res/anim/enter_bottom_to_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/anim/enter_left_to_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/anim/enter_right_to_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/anim/enter_top_to_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/anim/exit_left_to_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/anim/exit_right_to_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/anim/exit_top_to_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/anim/no_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/color/cal_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/onboard1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable-xxhdpi/onboard1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/onboard2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable-xxhdpi/onboard2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/onboard3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable-xxhdpi/onboard3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/onboard4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable-xxhdpi/onboard4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/onboard5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable-xxhdpi/onboard5.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/splashlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable-xxhdpi/splashlogo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/uwbanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable-xxhdpi/uwbanner.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/active.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/avatar.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/calendar.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/calendar_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/calendar_highlighted.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/check.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/check2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/check2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/clipboard.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/clock.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/contact.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/contacticon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/contacticon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/current_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/current_1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/current_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/current_2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/current_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/current_3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/current_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/current_4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/datalength.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/datalength.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/deactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/deactive.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/done_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/done_1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/done_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/done_2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/done_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/done_3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_gray_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_android_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_back_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_chevron_right_gray_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_close_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete_gray_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_edit_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_edit_gray_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_file_download_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_help.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_history_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_info_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_info_outline_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyboard_arrow_down_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_keyboard_arrow_down_gray_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_language_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_lock_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_more_vert_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_more_vert_gray_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_my_location_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_navigate_before_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_navigate_next_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_refresh_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_send_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_settings_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_warning_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_broadcast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/icon_broadcast.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_faq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/icon_faq.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_faq2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/icon_faq2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_health.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/icon_health.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/icon_phone.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_phone2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/icon_phone2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_phone3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/icon_phone3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_quarantine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/icon_quarantine.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/icon_share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_share2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/icon_share2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_symptoms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/icon_symptoms.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/icon_test.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/importicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/importicon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/kclogo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/kclogo.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/lang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/lang.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/logo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/logo2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/logo_purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/logo_purple.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/map.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/map_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/map_header.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/mapicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/mapicon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/microsoftlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/microsoftlogo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/nav1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/nav1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/nav2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/nav2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/nav3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/nav3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/onboard1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/onboard1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/onboard2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/onboard2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/onboard3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/onboard3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/onboard4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/onboard4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/onboard5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/onboard5.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/people.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/people.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/perm1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/perm1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/perm2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/perm2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/perm3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/perm3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/person.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/person.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/rect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/rect.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/rect2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/rect2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/rect3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/rect3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/report.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/res1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/res1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/res2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/res2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/ring.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/rubbish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/rubbish.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/settings_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/settings_black.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/settings_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/settings_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/shadows.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/speech.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/speech.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/speech_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/speech_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/splashlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/splashlogo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/startbutton.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/stopbutton.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/switch_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/switch_off.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/switch_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/switch_on.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/switch_on_noring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/switch_on_noring.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/symptom_confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/symptom_confirm.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/symptom_confirm_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/symptom_confirm_header.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/symptom_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/symptom_done.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/symptom_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/symptom_edit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/symptom_recent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/symptom_recent.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/todo_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/todo_2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/todo_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/todo_3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/todo_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/todo_4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/uwbanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/uwbanner.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/uwlogopurple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/uwlogopurple.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/uwlogowhite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/uwlogowhite.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/warning.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/warning2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/warning2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/warning3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/covidsafe/App-Android/a621babad52d1d93ffc580bc68b24690bdfe0c87/app/src/main/res/drawable/warning3.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 21 | 22 | 33 | 34 | 45 | 46 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_onboarding.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/card_privacy_disclaimer.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 19 | 20 | 26 | 27 | 28 | 35 | 36 | 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/res/layout/card_privacy_disclaimer3.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 18 | 19 | 23 | 24 | 32 | 33 | 34 | 35 | 42 | 43 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/res/layout/checkbox.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/contact_trace_pager.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/contact_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 28 | 29 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/layout/faq_answer.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 28 | 29 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/faq_question.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 23 | 24 | 32 | 33 | 45 | 46 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/faq_row.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_contact_log.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 21 | 22 | 27 | 28 | 29 | 30 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_history.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_import.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/health_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 21 | 22 | 27 | 28 | 29 | 30 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/health_main_old.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 18 | 19 | 22 | 23 | 24 | 25 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/import_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 28 | 29 | 40 | 41 |