From e917bd2fc33983d1a3194a032b1f2a1cc3879502 Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Mon, 30 May 2022 15:23:43 -0700 Subject: [PATCH] Include the voice network when determining the overall security. https://redmine.stoutner.com/issues/851 --- .../activities/PrivacyCellActivity.kt | 285 +++++++++--------- .../privacycell/helpers/ProtocolHelper.kt | 125 ++++++++ .../services/RealtimeMonitoringService.kt | 197 ++++++------ .../res/layout/privacy_cell_bottom_appbar.xml | 13 +- .../res/layout/privacy_cell_top_appbar.xml | 13 +- app/src/main/res/values-night/colors.xml | 1 + app/src/main/res/values/colors.xml | 1 + 7 files changed, 394 insertions(+), 241 deletions(-) create mode 100644 app/src/main/java/com/stoutner/privacycell/helpers/ProtocolHelper.kt diff --git a/app/src/main/java/com/stoutner/privacycell/activities/PrivacyCellActivity.kt b/app/src/main/java/com/stoutner/privacycell/activities/PrivacyCellActivity.kt index 16772d2..b158e05 100644 --- a/app/src/main/java/com/stoutner/privacycell/activities/PrivacyCellActivity.kt +++ b/app/src/main/java/com/stoutner/privacycell/activities/PrivacyCellActivity.kt @@ -55,16 +55,23 @@ import com.google.android.material.navigation.NavigationView import com.stoutner.privacycell.R import com.stoutner.privacycell.dialogs.PhonePermissionDialog import com.stoutner.privacycell.dialogs.WebViewDialog +import com.stoutner.privacycell.helpers.ProtocolHelper import com.stoutner.privacycell.services.RealtimeMonitoringService class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, PhonePermissionDialog.StoragePermissionDialogListener { + // Define the class variables. + private var voiceNetworkSecurityStatus = ProtocolHelper.UNPOPULATED + private var dataNetworkSecurityStatus = ProtocolHelper.UNPOPULATED + // Declare the class variables. - private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle private lateinit var phoneStateListener: PhoneStateListener // The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31. // Declare the class views. + private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle private lateinit var drawerLayout: DrawerLayout - private lateinit var summaryTextView: TextView + private lateinit var overallStatusLinearLayout: LinearLayout + private lateinit var overallStatusImageView: ImageView + private lateinit var overallStatusTextView: TextView override fun onCreate(savedInstanceState: Bundle?) { // Run the default commands. @@ -88,9 +95,9 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem // Get handles for the views. drawerLayout = findViewById(R.id.drawerlayout) val toolbar = findViewById(R.id.toolbar) - val stingrayLinearLayout = findViewById(R.id.stingray_linearlayout) - val stingrayImageView = findViewById(R.id.stingray_imageview) - summaryTextView = findViewById(R.id.summary_textview) + overallStatusLinearLayout = findViewById(R.id.overall_status_linearlayout) + overallStatusImageView = findViewById(R.id.overall_status_imageview) + overallStatusTextView = findViewById(R.id.overall_status_textview) val voiceNetworkLinearLayout = findViewById(R.id.voice_network_linearlayout) val voiceNetworkTextView = findViewById(R.id.voice_network) val voiceNetworkDetailsTextView = findViewById(R.id.voice_network_details) @@ -140,83 +147,40 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem } }) + // Instantiate the protocol helper. + val protocolHelper = ProtocolHelper() + // Define the phone state listener. The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31. phoneStateListener = object : PhoneStateListener() { @Deprecated("Deprecated in Java") - @SuppressLint("SwitchIntDef") - override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) { - // Declare the stingray dialog type integer. - val summaryDialogTypeInteger: Int - - // Populate the stingray security information. - if ((telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_IWLAN) || - (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN)) { // This is a secure network. - // Populate the image view. - stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.secure)) - - // Set the text. - summaryTextView.text = getString(R.string.secure_protocols) - - // Set the text color. - summaryTextView.setTextColor(getColor(R.color.blue_text)) - - // Set the stingray dialog type integer. - summaryDialogTypeInteger = WebViewDialog.STINGRAY - } else if ((telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_LTE) || (!consider3gAntiquated && (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_1xRTT || - (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EVDO_0) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EVDO_A) || - (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EVDO_B) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EHRPD) || - (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_UMTS) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_TD_SCDMA) || - (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSDPA) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSUPA) || - (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSPA) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSPAP)))) { - // This is an insecure network. - // Populate the image view. - stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.insecure)) - - // Set the text. - summaryTextView.text = getString(R.string.insecure_protocols) - - // Set the text color. - summaryTextView.setTextColor(getColor(R.color.yellow_900)) - - // Set the stingray dialog type integer. - summaryDialogTypeInteger = WebViewDialog.STINGRAY - } else { // This is an antiquated network. - // Populate the image view. - stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.antiquated)) - - // Set the text. - summaryTextView.text = getString(R.string.antiquated_protocols) - - // Set the text color. - summaryTextView.setTextColor(getColor(R.color.red_text)) - - // Set the stingray dialog type integer. - summaryDialogTypeInteger = WebViewDialog.ANTIQUATED_NETWORK - } + override fun onServiceStateChanged(serviceState: ServiceState) { // Update the voice network. + // Get the network registration info for the voice network, which is the second of the three entries (the first appears to be Wi-Fi and the third appears to be the cell data network). + val networkRegistrationInfo = serviceState.networkRegistrationInfoList[1] - // Get the strings that correspond to the network information. - val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType) - val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType) + // Get the voice network type int. + val voiceNetworkTypeInt = networkRegistrationInfo.accessNetworkTechnology - // Populate the data network text views. - dataNetworkTextView.text = getString(R.string.data_network, dataNetworkType[0]) - dataNetworkDetailsTextView.text = dataNetworkType[1] - additionalNetworkInfoTextView.text = getString(R.string.additional_network_info, additionalNetworkInfo[0]) - additionalNetworkInfoDetailsTextView.text = additionalNetworkInfo[1] + // Get the voice network security status. + voiceNetworkSecurityStatus = protocolHelper.checkNetwork(voiceNetworkTypeInt, consider3gAntiquated) - // Set the stingray click listener. - stingrayLinearLayout.setOnClickListener { - // Instantiate the stingray dialog fragment. - val stingrayDialogFragment = WebViewDialog().type(summaryDialogTypeInteger) + // Get the voice network type. + val voiceNetworkStringArray = protocolHelper.getNetworkTypeStringArray(voiceNetworkTypeInt, applicationContext) - // Show the alert dialog. - stingrayDialogFragment.show(supportFragmentManager, getString(R.string.stingrays)) + // Populate the voice network text views. + voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkStringArray[0]) + voiceNetworkDetailsTextView.text = voiceNetworkStringArray[1] + + // Set the color of the voice network. + when (voiceNetworkSecurityStatus) { + ProtocolHelper.SECURE -> voiceNetworkTextView.setTextColor(getColor(R.color.blue_text)) + ProtocolHelper.INSECURE -> voiceNetworkTextView.setTextColor(getColor(R.color.yellow_text)) + ProtocolHelper.ANTIQUATED -> voiceNetworkTextView.setTextColor(getColor(R.color.red_text)) } - // Set the data network click listener. - dataNetworkLinearLayout.setOnClickListener { - // Instantiate the data network dialog fragment according to the network type. - val dataNetworkDialogFragment = when (telephonyDisplayInfo.networkType) { + // Set the voice network click listener. + voiceNetworkLinearLayout.setOnClickListener { + // Instantiate the voice network dialog fragment according to the network type. + val voiceNetworkDialogFragment = when (voiceNetworkTypeInt) { TelephonyManager.NETWORK_TYPE_UNKNOWN -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN) TelephonyManager.NETWORK_TYPE_GPRS -> WebViewDialog().type(WebViewDialog.NETWORK_GPRS) TelephonyManager.NETWORK_TYPE_EDGE -> WebViewDialog().type(WebViewDialog.NETWORK_EDGE) @@ -241,43 +205,51 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem } // Show the alert dialog. - dataNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network)) + voiceNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network)) } - // Set the additional network info click listener. - additionalNetworkInfoLinearLayout.setOnClickListener { - // Instantiate the initial network info dialog fragment according to the network type. - val additionalNetworkInfoDialogFragment = when (telephonyDisplayInfo.overrideNetworkType) { - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NONE) - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_CA) - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_ADVANCED_PRO) - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA) - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE) // Can be removed once the minimum API >= 31. - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_ADVANCED) - else -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NONE) - } - - // Show the alert dialog. - additionalNetworkInfoDialogFragment.show(supportFragmentManager, getString(R.string.voice_network)) - } + // Populate the overall security status. + populateOverallSecurityStatus() } @Deprecated("Deprecated in Java") - override fun onServiceStateChanged(serviceState: ServiceState) { - // Get the network registration info for the voice network, which is the second of the three entries (the first appears to be Wi-Fi and the third appears to be the cell data network). - val networkRegistrationInfo = serviceState.networkRegistrationInfoList[1] + @SuppressLint("SwitchIntDef") + override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) { // Update the data network. + // Get the network type integers. + val dataNetworkTypeInt = telephonyDisplayInfo.networkType + val additionalNetworkInfoTypeInt = telephonyDisplayInfo.overrideNetworkType - // Get the voice network type. - val voiceNetworkType = getNetworkType(networkRegistrationInfo.accessNetworkTechnology) + // Get the data network security status. + dataNetworkSecurityStatus = protocolHelper.checkNetwork(dataNetworkTypeInt, consider3gAntiquated) - // Populate the voice network text views. - voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0]) - voiceNetworkDetailsTextView.text = voiceNetworkType[1] + // Get the strings that correspond to the network information. + val dataNetworkStringArray = protocolHelper.getNetworkTypeStringArray(dataNetworkTypeInt, applicationContext) + val additionalNetworkInfoStringArray = protocolHelper.getAdditionalNetworkInfoStringArray(additionalNetworkInfoTypeInt, applicationContext) - // Set the voice network click listener. - voiceNetworkLinearLayout.setOnClickListener { - // Instantiate the voice network dialog fragment according to the network type. - val voiceNetworkDialogFragment = when (networkRegistrationInfo.accessNetworkTechnology) { + // Populate the data network text views. + dataNetworkTextView.text = getString(R.string.data_network, dataNetworkStringArray[0]) + dataNetworkDetailsTextView.text = dataNetworkStringArray[1] + additionalNetworkInfoTextView.text = getString(R.string.additional_network_info, additionalNetworkInfoStringArray[0]) + additionalNetworkInfoDetailsTextView.text = additionalNetworkInfoStringArray[1] + + // Set the color of the data network. + when (dataNetworkSecurityStatus) { + ProtocolHelper.SECURE -> dataNetworkTextView.setTextColor(getColor(R.color.blue_text)) + ProtocolHelper.INSECURE -> dataNetworkTextView.setTextColor(getColor(R.color.yellow_text)) + ProtocolHelper.ANTIQUATED -> dataNetworkTextView.setTextColor(getColor(R.color.red_text)) + } + + // Set the color of the additional network info. + when (protocolHelper.checkAdditionalNetworkInfo(additionalNetworkInfoTypeInt)) { + ProtocolHelper.SECURE -> additionalNetworkInfoTextView.setTextColor(getColor(R.color.blue_text)) + ProtocolHelper.INSECURE -> additionalNetworkInfoTextView.setTextColor(getColor(R.color.yellow_text)) + ProtocolHelper.ANTIQUATED -> additionalNetworkInfoTextView.setTextColor(getColor(R.color.red_text)) + } + + // Set the data network click listener. + dataNetworkLinearLayout.setOnClickListener { + // Instantiate the data network dialog fragment according to the network type. + val dataNetworkDialogFragment = when (dataNetworkTypeInt) { TelephonyManager.NETWORK_TYPE_UNKNOWN -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN) TelephonyManager.NETWORK_TYPE_GPRS -> WebViewDialog().type(WebViewDialog.NETWORK_GPRS) TelephonyManager.NETWORK_TYPE_EDGE -> WebViewDialog().type(WebViewDialog.NETWORK_EDGE) @@ -302,8 +274,28 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem } // Show the alert dialog. - voiceNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network)) + dataNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network)) } + + // Set the additional network info click listener. + additionalNetworkInfoLinearLayout.setOnClickListener { + // Instantiate the initial network info dialog fragment according to the network type. + val additionalNetworkInfoDialogFragment = when (telephonyDisplayInfo.overrideNetworkType) { + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NONE) + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_CA) + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_ADVANCED_PRO) + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA) + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE) // Can be removed once the minimum API >= 31. + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_ADVANCED) + else -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NONE) + } + + // Show the alert dialog. + additionalNetworkInfoDialogFragment.show(supportFragmentManager, getString(R.string.voice_network)) + } + + // Populate the overall security status. + populateOverallSecurityStatus() } } @@ -514,7 +506,7 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem registerTelephonyManagerListener() } else { // The read phone state permission was denied. // Display the phone permission text on the main activity. - summaryTextView.text = getString(R.string.phone_permission_text) + overallStatusTextView.text = getString(R.string.phone_permission_text) } } } @@ -524,46 +516,59 @@ class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItem val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager // Listen to changes in the cell network state. The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31. - telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED or PhoneStateListener.LISTEN_SERVICE_STATE) + telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE or PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) } - private fun getNetworkType(networkType: Int) : Array { - // Return the string that corresponds to the network type. - return when(networkType) { - TelephonyManager.NETWORK_TYPE_UNKNOWN -> arrayOf(getString(R.string.unknown), "") - TelephonyManager.NETWORK_TYPE_GPRS -> arrayOf(getString(R.string.gprs), getString(R.string.gprs_detail)) - TelephonyManager.NETWORK_TYPE_EDGE -> arrayOf(getString(R.string.edge), getString(R.string.edge_detail)) - TelephonyManager.NETWORK_TYPE_UMTS -> arrayOf(getString(R.string.umts), getString(R.string.umts_detail)) - TelephonyManager.NETWORK_TYPE_CDMA -> arrayOf(getString(R.string.cdma), getString(R.string.cdma_detail)) - TelephonyManager.NETWORK_TYPE_EVDO_0 -> arrayOf(getString(R.string.evdo_0), getString(R.string.evdo_0_detail)) - TelephonyManager.NETWORK_TYPE_EVDO_A -> arrayOf(getString(R.string.evdo_a), getString(R.string.evdo_a_detail)) - TelephonyManager.NETWORK_TYPE_1xRTT -> arrayOf(getString(R.string.rtt), getString(R.string.rtt_detail)) - TelephonyManager.NETWORK_TYPE_HSDPA -> arrayOf(getString(R.string.hsdpa), getString(R.string.hsdpa_detail)) - TelephonyManager.NETWORK_TYPE_HSUPA -> arrayOf(getString(R.string.hsupa), getString(R.string.hsupa_detail)) - TelephonyManager.NETWORK_TYPE_HSPA -> arrayOf(getString(R.string.hspa), getString(R.string.hspa_detail)) - TelephonyManager.NETWORK_TYPE_IDEN -> arrayOf(getString(R.string.iden), getString(R.string.iden_detail)) - TelephonyManager.NETWORK_TYPE_EVDO_B -> arrayOf(getString(R.string.evdo_b), getString(R.string.evdo_b_detail)) - TelephonyManager.NETWORK_TYPE_LTE -> arrayOf(getString(R.string.lte), getString(R.string.lte_detail)) - TelephonyManager.NETWORK_TYPE_EHRPD -> arrayOf(getString(R.string.ehrpd), getString(R.string.ehrpd_detail)) - TelephonyManager.NETWORK_TYPE_HSPAP -> arrayOf(getString(R.string.hspap), getString(R.string.hspap_detail)) - TelephonyManager.NETWORK_TYPE_GSM -> arrayOf(getString(R.string.gsm), getString(R.string.gsm_detail)) - TelephonyManager.NETWORK_TYPE_TD_SCDMA -> arrayOf(getString(R.string.td_scdma), getString(R.string.td_scdma_detail)) - TelephonyManager.NETWORK_TYPE_IWLAN -> arrayOf(getString(R.string.iwlan), getString(R.string.iwlan_detail)) - TelephonyManager.NETWORK_TYPE_NR -> arrayOf(getString(R.string.nr), getString(R.string.nr_detail)) - else -> arrayOf(getString(R.string.error), "") + private fun populateOverallSecurityStatus() { + // Create an overall status dialog type integer. + val overallStatusDialogTypeInt: Int + + // Populate the over security status. + if ((voiceNetworkSecurityStatus == ProtocolHelper.ANTIQUATED) || (dataNetworkSecurityStatus == ProtocolHelper.ANTIQUATED)) { // This is an antiquated network. + // Populate the image view. + overallStatusImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.antiquated)) + + // Set the text. + overallStatusTextView.text = getString(R.string.antiquated_protocols) + + // Set the text color. + overallStatusTextView.setTextColor(getColor(R.color.red_text)) + + // Set the stingray dialog type integer. + overallStatusDialogTypeInt = WebViewDialog.ANTIQUATED_NETWORK + } else if ((voiceNetworkSecurityStatus == ProtocolHelper.INSECURE) || (dataNetworkSecurityStatus == ProtocolHelper.INSECURE)) { // This is an insecure network. + // Populate the image view. + overallStatusImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.insecure)) + + // Set the text. + overallStatusTextView.text = getString(R.string.insecure_protocols) + + // Set the text color. + overallStatusTextView.setTextColor(getColor(R.color.yellow_text)) + + // Set the stingray dialog type integer. + overallStatusDialogTypeInt = WebViewDialog.STINGRAY + } else { // This is a secure network. + // Populate the image view. + overallStatusImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.secure)) + + // Set the text. + overallStatusTextView.text = getString(R.string.secure_protocols) + + // Set the text color. + overallStatusTextView.setTextColor(getColor(R.color.blue_text)) + + // Set the stingray dialog type integer. + overallStatusDialogTypeInt = WebViewDialog.STINGRAY } - } - private fun getAdditionalNetworkInfo(overrideNetworkType: Int) : Array { - // Return the string that corresponds to the override network type. - return when(overrideNetworkType) { - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> arrayOf(getString(R.string.none), "") - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> arrayOf(getString(R.string.lte_ca), getString(R.string.lte_ca_detail)) - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> arrayOf(getString(R.string.lte_advanced_pro), getString(R.string.lte_advanced_pro_detail)) - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> arrayOf(getString(R.string.nr_nsa), getString(R.string.nr_nsa_detail)) - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> arrayOf(getString(R.string.nr_nsa_mmwave), getString(R.string.nr_nsa_mmwave_detail)) // Can be removed once the minimum API >= 31. - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED -> arrayOf(getString(R.string.nr_advanced), getString(R.string.nr_advanced_detail)) - else -> arrayOf(getString(R.string.error), "") + // Set the overall status click listener. + overallStatusLinearLayout.setOnClickListener { + // Instantiate the stingray dialog fragment. + val stingrayDialogFragment = WebViewDialog().type(overallStatusDialogTypeInt) + + // Show the alert dialog. + stingrayDialogFragment.show(supportFragmentManager, getString(R.string.stingrays)) } } } \ No newline at end of file diff --git a/app/src/main/java/com/stoutner/privacycell/helpers/ProtocolHelper.kt b/app/src/main/java/com/stoutner/privacycell/helpers/ProtocolHelper.kt new file mode 100644 index 0000000..dcbc9ad --- /dev/null +++ b/app/src/main/java/com/stoutner/privacycell/helpers/ProtocolHelper.kt @@ -0,0 +1,125 @@ +/* + * Copyright © 2022 Soren Stoutner . + * + * This file is part of Privacy Cell . + * + * Privacy Cell is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Privacy Cell is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Privacy Cell. If not, see . + */ + +package com.stoutner.privacycell.helpers + +import android.content.Context +import android.telephony.TelephonyDisplayInfo +import android.telephony.TelephonyManager + +import com.stoutner.privacycell.R + +class ProtocolHelper { + companion object { + // Define the public static companion object constants. + const val UNPOPULATED = -1 + const val SECURE = 0 + const val INSECURE = 1 + const val ANTIQUATED = 2 + } + + fun checkNetwork(networkType: Int, consider3gAntiquated: Boolean): Int { + if ((networkType == TelephonyManager.NETWORK_TYPE_NR) || + (networkType == TelephonyManager.NETWORK_TYPE_IWLAN) || + (networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN)) { + // The network is secure. + return SECURE + } else if (networkType == TelephonyManager.NETWORK_TYPE_LTE) { + // The network is insecure. + return INSECURE + } else if (!consider3gAntiquated && + ((networkType == TelephonyManager.NETWORK_TYPE_1xRTT) || + (networkType == TelephonyManager.NETWORK_TYPE_EVDO_0) || + (networkType == TelephonyManager.NETWORK_TYPE_EVDO_A) || + (networkType == TelephonyManager.NETWORK_TYPE_EVDO_B) || + (networkType == TelephonyManager.NETWORK_TYPE_EHRPD) || + (networkType == TelephonyManager.NETWORK_TYPE_UMTS) || + (networkType == TelephonyManager.NETWORK_TYPE_TD_SCDMA) || + (networkType == TelephonyManager.NETWORK_TYPE_HSDPA) || + (networkType == TelephonyManager.NETWORK_TYPE_HSUPA) || + (networkType == TelephonyManager.NETWORK_TYPE_HSPA) || + (networkType == TelephonyManager.NETWORK_TYPE_HSPAP))) { + // The network is insecure. + return INSECURE + } else { + // Either 3G networks are considered antiquated, or this is a 2G network. + // TelephonyManager.NETWORK_TYPE_GPRS + // TelephonyManager.NETWORK_TYPE_EDGE + // TelephonyManager.NETWORK_TYPE_CDMA + // TelephonyManager.NETWORK_TYPE_IDEN + // TelephonyManager.NETWORK_TYPE_GSM + return ANTIQUATED + } + } + + fun checkAdditionalNetworkInfo(additionalNetworkInfoType: Int): Int { + if ((additionalNetworkInfoType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) || + (additionalNetworkInfoType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED)) { + // The additional network info is secure. + return SECURE + } else { + // The additional network info is insecure. + // TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA + // TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO + // TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA + // TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -- Can be removed once the minimum API >= 31. + return INSECURE + } + } + + fun getNetworkTypeStringArray(networkType: Int, context: Context) : Array { + // Return the string array that corresponds to the network type. + return when(networkType) { + TelephonyManager.NETWORK_TYPE_UNKNOWN -> arrayOf(context.getString(R.string.unknown), "") + TelephonyManager.NETWORK_TYPE_GPRS -> arrayOf(context.getString(R.string.gprs), context.getString(R.string.gprs_detail)) + TelephonyManager.NETWORK_TYPE_EDGE -> arrayOf(context.getString(R.string.edge), context.getString(R.string.edge_detail)) + TelephonyManager.NETWORK_TYPE_UMTS -> arrayOf(context.getString(R.string.umts), context.getString(R.string.umts_detail)) + TelephonyManager.NETWORK_TYPE_CDMA -> arrayOf(context.getString(R.string.cdma), context.getString(R.string.cdma_detail)) + TelephonyManager.NETWORK_TYPE_EVDO_0 -> arrayOf(context.getString(R.string.evdo_0), context.getString(R.string.evdo_0_detail)) + TelephonyManager.NETWORK_TYPE_EVDO_A -> arrayOf(context.getString(R.string.evdo_a), context.getString(R.string.evdo_a_detail)) + TelephonyManager.NETWORK_TYPE_1xRTT -> arrayOf(context.getString(R.string.rtt), context.getString(R.string.rtt_detail)) + TelephonyManager.NETWORK_TYPE_HSDPA -> arrayOf(context.getString(R.string.hsdpa), context.getString(R.string.hsdpa_detail)) + TelephonyManager.NETWORK_TYPE_HSUPA -> arrayOf(context.getString(R.string.hsupa), context.getString(R.string.hsupa_detail)) + TelephonyManager.NETWORK_TYPE_HSPA -> arrayOf(context.getString(R.string.hspa), context.getString(R.string.hspa_detail)) + TelephonyManager.NETWORK_TYPE_IDEN -> arrayOf(context.getString(R.string.iden), context.getString(R.string.iden_detail)) + TelephonyManager.NETWORK_TYPE_EVDO_B -> arrayOf(context.getString(R.string.evdo_b), context.getString(R.string.evdo_b_detail)) + TelephonyManager.NETWORK_TYPE_LTE -> arrayOf(context.getString(R.string.lte), context.getString(R.string.lte_detail)) + TelephonyManager.NETWORK_TYPE_EHRPD -> arrayOf(context.getString(R.string.ehrpd), context.getString(R.string.ehrpd_detail)) + TelephonyManager.NETWORK_TYPE_HSPAP -> arrayOf(context.getString(R.string.hspap), context.getString(R.string.hspap_detail)) + TelephonyManager.NETWORK_TYPE_GSM -> arrayOf(context.getString(R.string.gsm), context.getString(R.string.gsm_detail)) + TelephonyManager.NETWORK_TYPE_TD_SCDMA -> arrayOf(context.getString(R.string.td_scdma), context.getString(R.string.td_scdma_detail)) + TelephonyManager.NETWORK_TYPE_IWLAN -> arrayOf(context.getString(R.string.iwlan), context.getString(R.string.iwlan_detail)) + TelephonyManager.NETWORK_TYPE_NR -> arrayOf(context.getString(R.string.nr), context.getString(R.string.nr_detail)) + else -> arrayOf(context.getString(R.string.error), "") + } + } + + fun getAdditionalNetworkInfoStringArray(overrideNetworkType: Int, context: Context) : Array { + // Return the string array that corresponds to the override network type. + return when(overrideNetworkType) { + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> arrayOf(context.getString(R.string.none), "") + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> arrayOf(context.getString(R.string.lte_ca), context.getString(R.string.lte_ca_detail)) + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> arrayOf(context.getString(R.string.lte_advanced_pro), context.getString(R.string.lte_advanced_pro_detail)) + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> arrayOf(context.getString(R.string.nr_nsa), context.getString(R.string.nr_nsa_detail)) + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> arrayOf(context.getString(R.string.nr_nsa_mmwave), context.getString(R.string.nr_nsa_mmwave_detail)) // Can be removed once the minimum API >= 31. + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED -> arrayOf(context.getString(R.string.nr_advanced), context.getString(R.string.nr_advanced_detail)) + else -> arrayOf(context.getString(R.string.error), "") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/stoutner/privacycell/services/RealtimeMonitoringService.kt b/app/src/main/java/com/stoutner/privacycell/services/RealtimeMonitoringService.kt index 68f9228..5d9ad3a 100644 --- a/app/src/main/java/com/stoutner/privacycell/services/RealtimeMonitoringService.kt +++ b/app/src/main/java/com/stoutner/privacycell/services/RealtimeMonitoringService.kt @@ -35,6 +35,7 @@ import android.content.pm.PackageManager import android.os.Binder import android.os.IBinder import android.telephony.PhoneStateListener // This can be replaced by `TelephonyCallback` once the minimum API >= 31. +import android.telephony.ServiceState import android.telephony.TelephonyDisplayInfo import android.telephony.TelephonyManager @@ -46,6 +47,7 @@ import androidx.work.WorkManager import com.stoutner.privacycell.R import com.stoutner.privacycell.activities.PrivacyCellActivity +import com.stoutner.privacycell.helpers.ProtocolHelper import com.stoutner.privacycell.workers.RegisterRealtimeListenerWorker import java.util.concurrent.TimeUnit @@ -65,7 +67,13 @@ class RealtimeMonitoringService : Service() { // Define the class variables. private var currentStatus = "" + private var voiceNetworkSecurityStatus = ProtocolHelper.UNPOPULATED + private var dataNetworkSecurityStatus = ProtocolHelper.UNPOPULATED + + // Declare the class variables. + private lateinit var notificationManager: NotificationManager private lateinit var phoneStateListener: PhoneStateListener // The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31. + private lateinit var privacyCellPendingIntent: PendingIntent inner class ServiceBinder : Binder() { // Get a copy of this service as a binder. @@ -85,7 +93,7 @@ class RealtimeMonitoringService : Service() { // So, the default value is set to true, which is the safest value if the shared preferences can't be queried. if (sharedPreferences.getBoolean(applicationContext.getString(R.string.realtime_monitoring_key), true)) { // Realtime monitoring is enabled. // Get a handle for the notification manager. - val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Create a notification channel group. notificationManager.createNotificationChannelGroup(NotificationChannelGroup(REALTIME_MONITORING, getString(R.string.realtime_monitoring))) @@ -126,7 +134,7 @@ class RealtimeMonitoringService : Service() { val privacyCellIntent = Intent(this, PrivacyCellActivity::class.java) // Create a pending intent from the Privacy Cell intent. - val privacyCellPendingIntent = PendingIntent.getActivity(this, 0, privacyCellIntent, PendingIntent.FLAG_IMMUTABLE) + privacyCellPendingIntent = PendingIntent.getActivity(this, 0, privacyCellIntent, PendingIntent.FLAG_IMMUTABLE) // Set the notification to open Privacy Cell. notificationBuilder.setContentIntent(privacyCellPendingIntent) @@ -143,94 +151,36 @@ class RealtimeMonitoringService : Service() { // Start the foreground notification. startForeground(NOTIFICATION_ID, notificationBuilder.build()) + // Instantiate the protocol helper. + val protocolHelper = ProtocolHelper() + // Define the phone state listener. The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31. phoneStateListener = object : PhoneStateListener() { @Deprecated("Deprecated in Java") - override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) { + override fun onServiceStateChanged(serviceState: ServiceState) { // Update the voice network status. + // Get the network registration info for the voice network, which is the second of the three entries (the first appears to be Wi-Fi and the third appears to be the cell data network). + val networkRegistrationInfo = serviceState.networkRegistrationInfoList[1] + + // Get the consider 3G antiquated preference. + val consider3gAntiquated = sharedPreferences.getBoolean(getString(R.string.consider_3g_antiquated_key), false) + + // Update the voice network security status. + voiceNetworkSecurityStatus = protocolHelper.checkNetwork(networkRegistrationInfo.accessNetworkTechnology, consider3gAntiquated) + + // Populate the notification. + populateNotification() + } + + @Deprecated("Deprecated in Java") + override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) { // Update the data network status. // Get the consider 3G antiquated preference. val consider3gAntiquated = sharedPreferences.getBoolean(getString(R.string.consider_3g_antiquated_key), false) - // Populate the notification according to the network type. - if ((telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_IWLAN) || - (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN)) { // This is a secure network. - // Only update the notification if the network status has changed. - if (currentStatus != SECURE_NETWORK) { - // Create a secure network notification builder. - val secureNetworkNotificationBuilder = Notification.Builder(applicationContext, SECURE_NETWORK) - - // Set the notification to open Privacy Cell. - secureNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent) - - // Set the notification text. - secureNetworkNotificationBuilder.setContentText(getString(R.string.secure_network)) - - // Set the notification icon. - secureNetworkNotificationBuilder.setSmallIcon(R.drawable.secure_notification_enabled) - - // Set the color. - secureNetworkNotificationBuilder.setColor(getColor(R.color.blue_icon)) - - // Update the notification. - notificationManager.notify(NOTIFICATION_ID, secureNetworkNotificationBuilder.build()) - - // Store the new network status. - currentStatus = SECURE_NETWORK - } - } else if ((telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_LTE) || (!consider3gAntiquated && (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_1xRTT || - (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EVDO_0) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EVDO_A) || - (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EVDO_B) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_EHRPD) || - (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_UMTS) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_TD_SCDMA) || - (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSDPA) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSUPA) || - (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSPA) || (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_HSPAP)))) { - // This is an insecure network. - // Only update the notification if the network status has changed. - if (currentStatus != INSECURE_NETWORK) { - // Create an insecure network notification builder. - val insecureNetworkNotificationBuilder = Notification.Builder(applicationContext, INSECURE_NETWORK) - - // Set the notification to open Privacy Cell. - insecureNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent) - - // Set the notification text. - insecureNetworkNotificationBuilder.setContentText(getString(R.string.insecure_network)) - - // Set the notification icon. - insecureNetworkNotificationBuilder.setSmallIcon(R.drawable.insecure_notification_enabled) - - // Set the color. - insecureNetworkNotificationBuilder.setColor(getColor(R.color.yellow_notification_icon)) - - // Update the notification. - notificationManager.notify(NOTIFICATION_ID, insecureNetworkNotificationBuilder.build()) - - // Store the new network status. - currentStatus = INSECURE_NETWORK - } - } else { // This is an antiquated network. - // Only update the notification if the network status has changed. - if (currentStatus != ANTIQUATED_NETWORK) { - // Create an antiquated network notification builder. - val antiquatedNetworkNotificationBuilder = Notification.Builder(applicationContext, ANTIQUATED_NETWORK) - - // Set the notification to open Privacy Cell. - antiquatedNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent) - - // Set the notification text. - antiquatedNetworkNotificationBuilder.setContentText(getString(R.string.antiquated_network)) - - // Set the notification icon. - antiquatedNetworkNotificationBuilder.setSmallIcon(R.drawable.antiquated_notification_enabled) - - // Set the color. - antiquatedNetworkNotificationBuilder.setColor(getColor(R.color.red_notification_icon)) - - // Update the notification. - notificationManager.notify(NOTIFICATION_ID, antiquatedNetworkNotificationBuilder.build()) - - // Store the new network status. - currentStatus = ANTIQUATED_NETWORK - } - } + // Update the data network security status. + dataNetworkSecurityStatus = protocolHelper.checkNetwork(telephonyDisplayInfo.networkType, consider3gAntiquated) + + // Populate the notification. + populateNotification() } } @@ -262,7 +212,84 @@ class RealtimeMonitoringService : Service() { telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE) // Listen for changes to the phone state. The `PhoneStateListener` can be replaced by `TelephonyCallback` once the minimum API >= 31. - telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) + telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE or PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) + } + } + + fun populateNotification() { + // Populate the notification according to the security status. + if ((voiceNetworkSecurityStatus == ProtocolHelper.ANTIQUATED) || (dataNetworkSecurityStatus == ProtocolHelper.ANTIQUATED)) { // This is an antiquated network. + // Only update the notification if the network status has changed. + if (currentStatus != ANTIQUATED_NETWORK) { + // Create an antiquated network notification builder. + val antiquatedNetworkNotificationBuilder = Notification.Builder(applicationContext, ANTIQUATED_NETWORK) + + // Set the notification to open Privacy Cell. + antiquatedNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent) + + // Set the notification text. + antiquatedNetworkNotificationBuilder.setContentText(getString(R.string.antiquated_network)) + + // Set the notification icon. + antiquatedNetworkNotificationBuilder.setSmallIcon(R.drawable.antiquated_notification_enabled) + + // Set the color. + antiquatedNetworkNotificationBuilder.setColor(getColor(R.color.red_notification_icon)) + + // Update the notification. + notificationManager.notify(NOTIFICATION_ID, antiquatedNetworkNotificationBuilder.build()) + + // Store the new network status. + currentStatus = ANTIQUATED_NETWORK + } + } else if ((voiceNetworkSecurityStatus == ProtocolHelper.INSECURE) || (dataNetworkSecurityStatus == ProtocolHelper.INSECURE)) { // This is an insecure network. + // Only update the notification if the network status has changed. + if (currentStatus != INSECURE_NETWORK) { + // Create an insecure network notification builder. + val insecureNetworkNotificationBuilder = Notification.Builder(applicationContext, INSECURE_NETWORK) + + // Set the notification to open Privacy Cell. + insecureNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent) + + // Set the notification text. + insecureNetworkNotificationBuilder.setContentText(getString(R.string.insecure_network)) + + // Set the notification icon. + insecureNetworkNotificationBuilder.setSmallIcon(R.drawable.insecure_notification_enabled) + + // Set the color. + insecureNetworkNotificationBuilder.setColor(getColor(R.color.yellow_notification_icon)) + + // Update the notification. + notificationManager.notify(NOTIFICATION_ID, insecureNetworkNotificationBuilder.build()) + + // Store the new network status. + currentStatus = INSECURE_NETWORK + } + } else { // This is a secure network. + // Only update the notification if the network status has changed. + if (currentStatus != SECURE_NETWORK) { + // Create a secure network notification builder. + val secureNetworkNotificationBuilder = Notification.Builder(applicationContext, SECURE_NETWORK) + + // Set the notification to open Privacy Cell. + secureNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent) + + // Set the notification text. + secureNetworkNotificationBuilder.setContentText(getString(R.string.secure_network)) + + // Set the notification icon. + secureNetworkNotificationBuilder.setSmallIcon(R.drawable.secure_notification_enabled) + + // Set the color. + secureNetworkNotificationBuilder.setColor(getColor(R.color.blue_icon)) + + // Update the notification. + notificationManager.notify(NOTIFICATION_ID, secureNetworkNotificationBuilder.build()) + + // Store the new network status. + currentStatus = SECURE_NETWORK + } } } } \ No newline at end of file diff --git a/app/src/main/res/layout/privacy_cell_bottom_appbar.xml b/app/src/main/res/layout/privacy_cell_bottom_appbar.xml index cdc2850..b4720dc 100644 --- a/app/src/main/res/layout/privacy_cell_bottom_appbar.xml +++ b/app/src/main/res/layout/privacy_cell_bottom_appbar.xml @@ -1,7 +1,7 @@ + @@ -121,7 +120,6 @@ android:layout_width="wrap_content" android:layout_gravity="center_horizontal" android:textAlignment="center" - android:textColor="@color/blue_text" android:textSize="18sp" android:textStyle="bold" /> @@ -148,7 +146,6 @@ android:layout_width="wrap_content" android:layout_gravity="center_horizontal" android:textAlignment="center" - android:textColor="@color/blue_text" android:textSize="18sp" android:textStyle="bold" /> diff --git a/app/src/main/res/layout/privacy_cell_top_appbar.xml b/app/src/main/res/layout/privacy_cell_top_appbar.xml index 356f084..b9d92b7 100644 --- a/app/src/main/res/layout/privacy_cell_top_appbar.xml +++ b/app/src/main/res/layout/privacy_cell_top_appbar.xml @@ -1,7 +1,7 @@ + @@ -133,7 +132,6 @@ android:layout_width="wrap_content" android:layout_gravity="center_horizontal" android:textAlignment="center" - android:textColor="@color/blue_text" android:textSize="18sp" android:textStyle="bold" /> @@ -160,7 +158,6 @@ android:layout_width="wrap_content" android:layout_gravity="center_horizontal" android:textAlignment="center" - android:textColor="@color/blue_text" android:textSize="18sp" android:textStyle="bold" /> diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index fe387b1..ef40f91 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -31,4 +31,5 @@ @color/red_900 @color/salmon @color/yellow_700 + @color/yellow_900 \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index a26fc5c..b70bf7b 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -31,6 +31,7 @@ @color/red_700 @color/red_700 @color/yellow_700 + @color/yellow_900 #FFFFD54F -- 2.45.2