2 * Copyright © 2021 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
6 * Privacy Cell is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Cell is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Cell. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacycell.activities
22 import android.Manifest
23 import android.app.ActivityManager
24 import android.content.Context
25 import android.content.Intent
26 import android.content.pm.PackageManager
27 import android.net.Uri
28 import android.os.Bundle
29 import android.telephony.PhoneStateListener
30 import android.telephony.ServiceState
31 import android.telephony.TelephonyDisplayInfo
32 import android.telephony.TelephonyManager
33 import android.view.MenuItem
34 import android.view.View
35 import android.widget.ImageView
36 import android.widget.LinearLayout
37 import android.widget.TextView
39 import androidx.appcompat.app.ActionBar
40 import androidx.appcompat.app.ActionBarDrawerToggle
41 import androidx.appcompat.app.AppCompatActivity
42 import androidx.appcompat.content.res.AppCompatResources
43 import androidx.appcompat.widget.Toolbar
44 import androidx.core.app.ActivityCompat
45 import androidx.core.view.GravityCompat
46 import androidx.drawerlayout.widget.DrawerLayout
47 import androidx.preference.PreferenceManager
49 import com.google.android.material.navigation.NavigationView
51 import com.stoutner.privacycell.R
52 import com.stoutner.privacycell.dialogs.PhonePermissionDialog
53 import com.stoutner.privacycell.dialogs.WebViewDialog
54 import com.stoutner.privacycell.services.RealtimeMonitoringService
56 class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, PhonePermissionDialog.StoragePermissionDialogListener {
57 // Declare the class variables.
58 private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
59 private lateinit var phoneStateListener: PhoneStateListener
61 // Declare the class views.
62 private lateinit var drawerLayout: DrawerLayout
63 private lateinit var stingrayTextView: TextView
65 override fun onCreate(savedInstanceState: Bundle?) {
66 // Run the default commands.
67 super.onCreate(savedInstanceState)
69 // Get a handle for the shared preferences.
70 val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
72 // Get the preferences.
73 val realtimeMonitoring = sharedPreferences.getBoolean(getString(R.string.realtime_monitoring_key), false)
74 val bottomAppBar = sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)
76 // Set the content view.
78 setContentView(R.layout.privacy_cell_bottom_appbar)
80 setContentView(R.layout.privacy_cell_top_appbar)
83 // Get handles for the views.
84 drawerLayout = findViewById(R.id.drawerlayout)
85 val toolbar = findViewById<Toolbar>(R.id.toolbar)
86 val stingrayLinearLayout = findViewById<LinearLayout>(R.id.stingray_linearlayout)
87 val stingrayImageView = findViewById<ImageView>(R.id.stingray_imageview)
88 stingrayTextView = findViewById(R.id.stingray_textview)
89 val voiceNetworkLinearLayout = findViewById<LinearLayout>(R.id.voice_network_linearlayout)
90 val voiceNetworkTextView = findViewById<TextView>(R.id.voice_network)
91 val voiceNetworkDetailsTextView = findViewById<TextView>(R.id.voice_network_details)
92 val dataNetworkLinearLayout = findViewById<LinearLayout>(R.id.data_network_linearlayout)
93 val dataNetworkTextView = findViewById<TextView>(R.id.data_network)
94 val dataNetworkDetailsTextView = findViewById<TextView>(R.id.data_network_details)
95 val additionalNetworkInfoLinearLayout = findViewById<LinearLayout>(R.id.additional_network_info_linearlayout)
96 val additionalNetworkInfoTextView = findViewById<TextView>(R.id.additional_network_info)
97 val additionalNetworkInfoDetailsTextView = findViewById<TextView>(R.id.additional_network_info_details)
98 val navigationView = findViewById<NavigationView>(R.id.navigationview)
100 // Set the support action bar.
101 setSupportActionBar(toolbar)
103 // Get a handle for the action bar.
104 val actionBar = supportActionBar!!
106 // Set a custom view on the action bar.
107 actionBar.setCustomView(R.layout.app_bar_textview)
109 // Display the custom view.
110 actionBar.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM
112 // Define a hamburger icon at the start of the app bar. It will be populated in `onPostCreate()`.
113 actionBarDrawerToggle = ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.open_navigation_drawer, R.string.close_navigation_drawer)
115 // Listen for touches on the navigation menu.
116 navigationView.setNavigationItemSelectedListener(this)
118 // Add a drawer listener.
119 drawerLayout.addDrawerListener(object : DrawerLayout.DrawerListener {
120 override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
124 override fun onDrawerOpened(drawerView: View) {
128 override fun onDrawerClosed(drawerView: View) {
129 // Reset the drawer icon when the drawer is closed. Otherwise, it is an arrow if the drawer is open when the app is restarted.
130 actionBarDrawerToggle.syncState()
133 override fun onDrawerStateChanged(newState: Int) {
138 // Define the phone state listener.
139 phoneStateListener = object : PhoneStateListener() {
140 override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
141 // Populate the stingray security information. <https://source.android.com/devices/tech/connect/acts-5g-testing>
142 if (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) { // This is a secure 5G NR SA network.
143 // Populate the image view.
144 stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.secure_5g_nr_sa))
147 stingrayTextView.text = getString(R.string.secure_from_stingray)
149 // Set the text color.
150 stingrayTextView.setTextColor(getColor(R.color.blue_text))
151 } else { // This is not a secure 5G NR SA network.
152 // Populate the image view.
153 stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(applicationContext, R.drawable.not_secure))
156 stingrayTextView.text = getString(R.string.not_secure_from_stingray)
158 // Set the text color.
159 stingrayTextView.setTextColor(getColor(R.color.red_text))
162 // Get the strings that correspond to the network information.
163 val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType)
164 val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType)
166 // Populate the data network text views.
167 dataNetworkTextView.text = getString(R.string.data_network, dataNetworkType[0])
168 dataNetworkDetailsTextView.text = dataNetworkType[1]
169 additionalNetworkInfoTextView.text = getString(R.string.additional_network_info, additionalNetworkInfo[0])
170 additionalNetworkInfoDetailsTextView.text = additionalNetworkInfo[1]
172 // Set the stingray click listener.
173 stingrayLinearLayout.setOnClickListener {
174 // Instantiate the stingray dialog fragment.
175 val stingrayDialogFragment = WebViewDialog().type(WebViewDialog.STINGRAY)
177 // Show the alert dialog.
178 stingrayDialogFragment.show(supportFragmentManager, getString(R.string.stingrays))
181 // Set the data network click listener.
182 dataNetworkLinearLayout.setOnClickListener {
183 // Instantiate the data network dialog fragment according to the network type.
184 val dataNetworkDialogFragment = when (telephonyDisplayInfo.networkType) {
185 TelephonyManager.NETWORK_TYPE_UNKNOWN -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
186 TelephonyManager.NETWORK_TYPE_GPRS -> WebViewDialog().type(WebViewDialog.NETWORK_GPRS)
187 TelephonyManager.NETWORK_TYPE_EDGE -> WebViewDialog().type(WebViewDialog.NETWORK_EDGE)
188 TelephonyManager.NETWORK_TYPE_UMTS -> WebViewDialog().type(WebViewDialog.NETWORK_UMTS)
189 TelephonyManager.NETWORK_TYPE_CDMA -> WebViewDialog().type(WebViewDialog.NETWORK_CDMA)
190 TelephonyManager.NETWORK_TYPE_EVDO_0 -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_0)
191 TelephonyManager.NETWORK_TYPE_EVDO_A -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_A)
192 TelephonyManager.NETWORK_TYPE_1xRTT -> WebViewDialog().type(WebViewDialog.NETWORK_1xRTT)
193 TelephonyManager.NETWORK_TYPE_HSDPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSDPA)
194 TelephonyManager.NETWORK_TYPE_HSUPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSUPA)
195 TelephonyManager.NETWORK_TYPE_HSPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSPA)
196 TelephonyManager.NETWORK_TYPE_IDEN -> WebViewDialog().type(WebViewDialog.NETWORK_IDEN)
197 TelephonyManager.NETWORK_TYPE_EVDO_B -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_B)
198 TelephonyManager.NETWORK_TYPE_LTE -> WebViewDialog().type(WebViewDialog.NETWORK_LTE)
199 TelephonyManager.NETWORK_TYPE_EHRPD -> WebViewDialog().type(WebViewDialog.NETWORK_EHRPD)
200 TelephonyManager.NETWORK_TYPE_HSPAP -> WebViewDialog().type(WebViewDialog.NETWORK_HSPAP)
201 TelephonyManager.NETWORK_TYPE_GSM -> WebViewDialog().type(WebViewDialog.NETWORK_GSM)
202 TelephonyManager.NETWORK_TYPE_TD_SCDMA -> WebViewDialog().type(WebViewDialog.NETWORK_TD_SCDMA)
203 TelephonyManager.NETWORK_TYPE_IWLAN -> WebViewDialog().type(WebViewDialog.NETWORK_IWLAN)
204 TelephonyManager.NETWORK_TYPE_NR -> WebViewDialog().type(WebViewDialog.NETWORK_NR)
205 else -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
208 // Show the alert dialog.
209 dataNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
212 // Set the additional network info click listener.
213 additionalNetworkInfoLinearLayout.setOnClickListener {
214 // Instantiate the initial network info dialog fragment according to the network type.
215 val additionalNetworkInfoDialogFragment = when (telephonyDisplayInfo.overrideNetworkType) {
216 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NONE)
217 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_CA)
218 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_ADVANCED_PRO)
219 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA)
220 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE)
221 else -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE)
224 // Show the alert dialog.
225 additionalNetworkInfoDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
229 override fun onServiceStateChanged(serviceState: ServiceState) {
230 // 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).
231 val networkRegistrationInfo = serviceState.networkRegistrationInfoList[1]
233 // Get the voice network type.
234 val voiceNetworkType = getNetworkType(networkRegistrationInfo.accessNetworkTechnology)
236 // Populate the voice network text views.
237 voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0])
238 voiceNetworkDetailsTextView.text = voiceNetworkType[1]
240 // Set the voice network click listener.
241 voiceNetworkLinearLayout.setOnClickListener {
242 // Instantiate the voice network dialog fragment according to the network type.
243 val voiceNetworkDialogFragment = when (networkRegistrationInfo.accessNetworkTechnology) {
244 TelephonyManager.NETWORK_TYPE_UNKNOWN -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
245 TelephonyManager.NETWORK_TYPE_GPRS -> WebViewDialog().type(WebViewDialog.NETWORK_GPRS)
246 TelephonyManager.NETWORK_TYPE_EDGE -> WebViewDialog().type(WebViewDialog.NETWORK_EDGE)
247 TelephonyManager.NETWORK_TYPE_UMTS -> WebViewDialog().type(WebViewDialog.NETWORK_UMTS)
248 TelephonyManager.NETWORK_TYPE_CDMA -> WebViewDialog().type(WebViewDialog.NETWORK_CDMA)
249 TelephonyManager.NETWORK_TYPE_EVDO_0 -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_0)
250 TelephonyManager.NETWORK_TYPE_EVDO_A -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_A)
251 TelephonyManager.NETWORK_TYPE_1xRTT -> WebViewDialog().type(WebViewDialog.NETWORK_1xRTT)
252 TelephonyManager.NETWORK_TYPE_HSDPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSDPA)
253 TelephonyManager.NETWORK_TYPE_HSUPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSUPA)
254 TelephonyManager.NETWORK_TYPE_HSPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSPA)
255 TelephonyManager.NETWORK_TYPE_IDEN -> WebViewDialog().type(WebViewDialog.NETWORK_IDEN)
256 TelephonyManager.NETWORK_TYPE_EVDO_B -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_B)
257 TelephonyManager.NETWORK_TYPE_LTE -> WebViewDialog().type(WebViewDialog.NETWORK_LTE)
258 TelephonyManager.NETWORK_TYPE_EHRPD -> WebViewDialog().type(WebViewDialog.NETWORK_EHRPD)
259 TelephonyManager.NETWORK_TYPE_HSPAP -> WebViewDialog().type(WebViewDialog.NETWORK_HSPAP)
260 TelephonyManager.NETWORK_TYPE_GSM -> WebViewDialog().type(WebViewDialog.NETWORK_GSM)
261 TelephonyManager.NETWORK_TYPE_TD_SCDMA -> WebViewDialog().type(WebViewDialog.NETWORK_TD_SCDMA)
262 TelephonyManager.NETWORK_TYPE_IWLAN -> WebViewDialog().type(WebViewDialog.NETWORK_IWLAN)
263 TelephonyManager.NETWORK_TYPE_NR -> WebViewDialog().type(WebViewDialog.NETWORK_NR)
264 else -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
267 // Show the alert dialog.
268 voiceNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
273 // Start the realtime monitoring service if it is enabled.
274 if (realtimeMonitoring) {
275 // Get a handle for the activity manager.
276 val activityManager: ActivityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
278 // Get a list of the running service info. The deprecated `getRunningServices()` now only returns services stared by Privacy Cell, but that is all we want to know anyway.
279 val runningServiceInfoList: List<ActivityManager.RunningServiceInfo> = activityManager.getRunningServices(1)
281 // Start the service if it is not already running.
282 if (runningServiceInfoList.isEmpty()) {
283 startService(Intent(this, RealtimeMonitoringService::class.java))
288 override fun onPostCreate(savedInstanceState: Bundle?) {
289 // Run the default commands.
290 super.onPostCreate(savedInstanceState)
292 // Sync the state of the DrawerToggle after the default `onRestoreInstanceState()` has finished. This creates the navigation drawer icon.
293 actionBarDrawerToggle.syncState()
296 override fun onStart() {
297 // Run the default commands.
300 // Check to see if the read phone state permission has been granted. These commands need to be run on every start so that the listener is reregistered.
301 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { // The storage permission has been granted.
302 // Register the telephony manager listener.
303 registerTelephonyManagerListener()
304 } else { // The phone permission has not been granted.
305 // Check if the user has previously denied the storage permission.
306 if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE)) { // Show a dialog explaining the request first.
307 // Check to see if a phone permission dialog is already displayed. This happens if the app is restarted when the dialog is shown.
308 if (supportFragmentManager.findFragmentByTag(getString(R.string.phone_permission)) == null) { // No dialog is currently shown.
309 // Instantiate the phone permission dialog fragment.
310 val phonePermissionDialogFragment = PhonePermissionDialog()
312 // Show the phone permission alert dialog. The permission will be requested when the dialog is closed.
313 phonePermissionDialogFragment.show(supportFragmentManager, getString(R.string.phone_permission))
315 } else { // Show the permission request directly.
316 // Request the read phone state permission. There is only one permission request in the app, so it has a request code of 0.
317 ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
322 override fun onStop() {
323 // Run the default commands.
326 // Get a handle for the telephony manager.
327 val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
329 // Unregister the telephony manager listener.
330 telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE)
333 override fun onNavigationItemSelected(menuItem: MenuItem) : Boolean {
334 // Run the commands that correspond to the selected menu item.
335 when (menuItem.itemId) {
336 R.id.settings -> { // Settings.
337 // Create an intent to load the Settings activity.
338 val settingsIntent = Intent(this, SettingsActivity::class.java)
341 startActivity(settingsIntent)
344 R.id.logcat -> { // Logcat.
345 // Create an intent to load the Logcat activity.
346 val logcatIntent = Intent(this, LogcatActivity::class.java)
349 startActivity(logcatIntent)
352 R.id.permissions -> { // Permissions.
353 // Instantiate the permissions dialog fragment.
354 val permissionsDialogFragment = WebViewDialog().type(WebViewDialog.PERMISSIONS)
356 // Show the alert dialog.
357 permissionsDialogFragment.show(supportFragmentManager, getString(R.string.permissions))
360 R.id.privacy_policy -> { // Privacy Policy.
361 // Instantiate the privacy policy dialog fragment.
362 val privacyPolicyDialogFragment = WebViewDialog().type(WebViewDialog.PRIVACY_POLICY)
364 // Show the alert dialog.
365 privacyPolicyDialogFragment.show(supportFragmentManager, getString(R.string.privacy_policy))
368 R.id.changelog -> { // Changelog.
369 // Instantiate the changelog dialog fragment.
370 val changelogDialogFragment = WebViewDialog().type(WebViewDialog.CHANGELOG)
372 // Show the alert dialog.
373 changelogDialogFragment.show(supportFragmentManager, getString(R.string.changelog))
376 R.id.licenses -> { // Licenses.
377 // Instantiate the licenses dialog fragment.
378 val licensesDialogFragment = WebViewDialog().type(WebViewDialog.LICENSES)
380 // Show the alert dialog.
381 licensesDialogFragment.show(supportFragmentManager, getString(R.string.licenses))
384 R.id.contributors -> { // Contributors.
385 // Instantiate the contributors dialog fragment.
386 val contributorsDialogFragment = WebViewDialog().type(WebViewDialog.CONTRIBUTORS)
388 // Show the alert dialog.
389 contributorsDialogFragment.show(supportFragmentManager, getString(R.string.contributors))
392 R.id.news -> { // News.
393 // Create a news URL intent.
394 val newsUrlIntent = Intent(Intent.ACTION_VIEW)
396 // Add the URL to the intent.
397 newsUrlIntent.data = Uri.parse("https://www.stoutner.com/category/privacy-cell/")
400 startActivity(newsUrlIntent)
403 R.id.roadmap -> { // Roadmap.
404 // Create a roadmap URL intent.
405 val roadmapUrlIntent = Intent(Intent.ACTION_VIEW)
407 // Add the URL to the intent.
408 roadmapUrlIntent.data = Uri.parse("https://www.stoutner.com/category/privacy-cell-roadmap/")
411 startActivity(roadmapUrlIntent)
414 R.id.bug_tracker -> { // Bug tracker.
415 // Create a bug tracker URL intent.
416 val bugTrackerUrlIntent = Intent(Intent.ACTION_VIEW)
418 // Add the URL to the intent.
419 bugTrackerUrlIntent.data = Uri.parse("https://redmine.stoutner.com/projects/privacy-cell/issues")
422 startActivity(bugTrackerUrlIntent)
425 R.id.forum -> { // Forum.
426 // Create a forum URL intent.
427 val forumUrlIntent = Intent(Intent.ACTION_VIEW)
429 // Add the URL to the intent.
430 forumUrlIntent.data = Uri.parse("https://redmine.stoutner.com/projects/privacy-cell/boards")
433 startActivity(forumUrlIntent)
436 R.id.donations -> { // Donations.
437 // Create a donations URL intent.
438 val donationsUrlIntent = Intent(Intent.ACTION_VIEW)
440 // Add the URL to the intent.
441 donationsUrlIntent.data = Uri.parse("https://www.stoutner.com/donations/")
444 startActivity(donationsUrlIntent)
448 // Close the navigation drawer.
449 drawerLayout.closeDrawer(GravityCompat.START)
451 // Consume the click.
455 override fun onCloseStoragePermissionDialog() {
456 // Request the read phone state permission. There is only one permission request in the app, so it has a request code of 0.
457 ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
460 override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
461 // Run the default commands.
462 super.onRequestPermissionsResult(requestCode, permissions, grantResults)
464 //Only process the results if they exist (this method is triggered when a dialog is presented the first time for an app, but no grant results are included).
465 if (grantResults.isNotEmpty()) {
466 // Check to see if the read phone state permission was granted. If the dialog was canceled the grant results will be empty.
467 if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // The read phone state permission was granted.
468 // Populate Privacy Cell.
469 registerTelephonyManagerListener()
470 } else { // The read phone state permission was denied.
471 // Display the phone permission text on the main activity.
472 stingrayTextView.text = getString(R.string.phone_permission_text)
477 private fun registerTelephonyManagerListener() {
478 // Get a handle for the telephony manager.
479 val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
481 // Listen to changes in the cell network state.
482 telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED or PhoneStateListener.LISTEN_SERVICE_STATE)
485 private fun getNetworkType(networkType: Int) : Array<String> {
486 // Return the string that corresponds to the network type.
487 return when(networkType) {
488 TelephonyManager.NETWORK_TYPE_UNKNOWN -> arrayOf(getString(R.string.unknown), "")
489 TelephonyManager.NETWORK_TYPE_GPRS -> arrayOf(getString(R.string.gprs), getString(R.string.gprs_detail))
490 TelephonyManager.NETWORK_TYPE_EDGE -> arrayOf(getString(R.string.edge), getString(R.string.edge_detail))
491 TelephonyManager.NETWORK_TYPE_UMTS -> arrayOf(getString(R.string.umts), getString(R.string.umts_detail))
492 TelephonyManager.NETWORK_TYPE_CDMA -> arrayOf(getString(R.string.cdma), getString(R.string.cdma_detail))
493 TelephonyManager.NETWORK_TYPE_EVDO_0 -> arrayOf(getString(R.string.evdo_0), getString(R.string.evdo_0_detail))
494 TelephonyManager.NETWORK_TYPE_EVDO_A -> arrayOf(getString(R.string.evdo_a), getString(R.string.evdo_a_detail))
495 TelephonyManager.NETWORK_TYPE_1xRTT -> arrayOf(getString(R.string.rtt), getString(R.string.rtt_detail))
496 TelephonyManager.NETWORK_TYPE_HSDPA -> arrayOf(getString(R.string.hsdpa), getString(R.string.hsdpa_detail))
497 TelephonyManager.NETWORK_TYPE_HSUPA -> arrayOf(getString(R.string.hsupa), getString(R.string.hsupa_detail))
498 TelephonyManager.NETWORK_TYPE_HSPA -> arrayOf(getString(R.string.hspa), getString(R.string.hspa_detail))
499 TelephonyManager.NETWORK_TYPE_IDEN -> arrayOf(getString(R.string.iden), getString(R.string.iden_detail))
500 TelephonyManager.NETWORK_TYPE_EVDO_B -> arrayOf(getString(R.string.evdo_b), getString(R.string.evdo_b_detail))
501 TelephonyManager.NETWORK_TYPE_LTE -> arrayOf(getString(R.string.lte), getString(R.string.lte_detail))
502 TelephonyManager.NETWORK_TYPE_EHRPD -> arrayOf(getString(R.string.ehrpd), getString(R.string.ehrpd_detail))
503 TelephonyManager.NETWORK_TYPE_HSPAP -> arrayOf(getString(R.string.hspap), getString(R.string.hspap_detail))
504 TelephonyManager.NETWORK_TYPE_GSM -> arrayOf(getString(R.string.gsm), getString(R.string.gsm_detail))
505 TelephonyManager.NETWORK_TYPE_TD_SCDMA -> arrayOf(getString(R.string.td_scdma), getString(R.string.td_scdma_detail))
506 TelephonyManager.NETWORK_TYPE_IWLAN -> arrayOf(getString(R.string.iwlan), getString(R.string.iwlan_detail))
507 TelephonyManager.NETWORK_TYPE_NR -> arrayOf(getString(R.string.nr), getString(R.string.nr_detail))
508 else -> arrayOf(getString(R.string.error), "")
512 private fun getAdditionalNetworkInfo(overrideNetworkType: Int) : Array<String> {
513 // Return the string that corresponds to the override network type.
514 return when(overrideNetworkType) {
515 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> arrayOf(getString(R.string.none), "")
516 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> arrayOf(getString(R.string.lte_ca), getString(R.string.lte_ca_detail))
517 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> arrayOf(getString(R.string.lte_advanced_pro), getString(R.string.lte_advanced_pro_detail))
518 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> arrayOf(getString(R.string.nr_nsa), getString(R.string.nr_nsa_detail))
519 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> arrayOf(getString(R.string.nr_nsa_mmwave), getString(R.string.nr_nsa_mmwave_detail))
520 else -> arrayOf(getString(R.string.error), "")