import android.content.pm.PackageManager
import android.os.Bundle
import android.telephony.PhoneStateListener
+import android.telephony.ServiceState
import android.telephony.TelephonyDisplayInfo
import android.telephony.TelephonyManager
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.app.ActivityCompat
+import androidx.fragment.app.DialogFragment
import com.stoutner.privacycell.R
+import com.stoutner.privacycell.dialogs.PhonePermissionDialog
+
+class PrivacyCell : AppCompatActivity(), PhonePermissionDialog.StoragePermissionDialogListener {
+ // Declare the class variables.
+ private lateinit var context: Context
+ private lateinit var telephonyManager: TelephonyManager
+
+ // Declare the views.
+ lateinit var secureFromStingrayImageView: ImageView
+ lateinit var secureFromStingrayTextView: TextView
+ lateinit var voiceNetworkTextView: TextView
+ lateinit var voiceNetworkDetailsTextView: TextView
+ lateinit var dataNetworkTextView: TextView
+ lateinit var dataNetworkDetailsTextView: TextView
+ lateinit var additionalNetworkInfoTextView: TextView
+ lateinit var additionalNetworkInfoDetailsTextView: TextView
-class PrivacyCell : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// Run the default commands.
super.onCreate(savedInstanceState)
// Set the content view.
- setContentView(R.layout.privacy_cell_linearlayout)
+ setContentView(R.layout.privacy_cell_scrollview)
// Get handles for the views.
- val secureFromStingrayImageView = findViewById<ImageView>(R.id.secure_from_stingray_imageview)
- val secureFromStingrayTextView = findViewById<TextView>(R.id.secure_from_stingray_textview)
- val voiceNetworkTextView = findViewById<TextView>(R.id.voice_network)
- val voiceNetworkDetailsTextView = findViewById<TextView>(R.id.voice_network_details)
- val dataNetworkTextView = findViewById<TextView>(R.id.data_network)
- val dataNetworkDetailsTextView = findViewById<TextView>(R.id.data_network_details)
- val additionalNetworkInfoTextView = findViewById<TextView>(R.id.additional_network_info)
- val additionalNetworkInfoDetailsTextView = findViewById<TextView>(R.id.additional_network_info_details)
-
- // TODO.
- if (ActivityCompat.checkSelfPermission(
- this,
- Manifest.permission.READ_PHONE_STATE
- ) != PackageManager.PERMISSION_GRANTED
- ) {
- // TODO: Consider calling
- // ActivityCompat#requestPermissions
- // here to request the missing permissions, and then overriding
- // public void onRequestPermissionsResult(int requestCode, String[] permissions,
- // int[] grantResults)
- // to handle the case where the user grants the permission. See the documentation
- // for ActivityCompat#requestPermissions for more details.
- return
+ secureFromStingrayImageView = findViewById(R.id.secure_from_stingray_imageview)
+ secureFromStingrayTextView = findViewById(R.id.secure_from_stingray_textview)
+ voiceNetworkTextView = findViewById(R.id.voice_network)
+ voiceNetworkDetailsTextView = findViewById(R.id.voice_network_details)
+ dataNetworkTextView = findViewById(R.id.data_network)
+ dataNetworkDetailsTextView = findViewById(R.id.data_network_details)
+ additionalNetworkInfoTextView = findViewById(R.id.additional_network_info)
+ additionalNetworkInfoDetailsTextView = findViewById(R.id.additional_network_info_details)
+
+ // Get handles for the context and the telephony manager.
+ context = this
+ telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
+
+ // Check to see if the read phone state permission has been granted.
+ if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { // The storage permission has been granted.
+ // Populate Privacy Cell.
+ populatePrivacyCell()
+ } else { // The phone permission has not been granted.
+ // Check if the user has previously denied the storage permission.
+ if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE)) { // Show a dialog explaining the request first.
+ // Check to see if a phone permission dialog is already displayed. This happens if the app is restarted when the dialog is shown.
+ if (supportFragmentManager.findFragmentByTag(getString(R.string.phone_permission)) == null) { // No dialog is currently shown.
+ // Instantiate the phone permission dialog fragment.
+ val phonePermissionDialogFragment: DialogFragment = PhonePermissionDialog()
+
+ // Show the phone permission alert dialog. The permission will be requested when the dialog is closed.
+ phonePermissionDialogFragment.show(supportFragmentManager, getString(R.string.phone_permission))
+ }
+ } else { // Show the permission request directly.
+ // Request the read phone state permission. There is only one permission request in the app, so it has a request code of 0.
+ ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
+ }
}
+ }
- // Get a handle for the the telephone Manager and the context.
- val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
- val context: Context = this
-
- // Get the voice network type.
- val voiceNetworkType = getNetworkType(telephonyManager.voiceNetworkType)
+ override fun onCloseStoragePermissionDialog() {
+ // Request the read phone state permission. There is only one permission request in the app, so it has a request code of 0.
+ ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
+ }
- // Populate the voice network text views.
- voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0])
- voiceNetworkDetailsTextView.text = voiceNetworkType[1]
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
+ // Run the default commands.
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+
+ //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).
+ if (grantResults.isNotEmpty()) {
+ // Check to see if the read phone state permission was granted. If the dialog was canceled the grant results will be empty.
+ if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // The read phone state permission was granted.
+ // Populate Privacy Cell.
+ populatePrivacyCell()
+ } else { // The read phone state permission was denied.
+ // Display the phone permission text on the main activity.
+ secureFromStingrayTextView.text = getString(R.string.phone_permission_text)
+ }
+ }
+ }
+ private fun populatePrivacyCell() {
// Listen to changes in the cell network state.
telephonyManager.listen(object : PhoneStateListener() {
- override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {// Populate the secure from stingray text view. <https://source.android.com/devices/tech/connect/acts-5g-testing>
- // Populate the stingray security information.
+ override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
+ // Populate the stingray security information. <https://source.android.com/devices/tech/connect/acts-5g-testing>
if (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) { // This is a secure 5G NR SA network.
// Populate the image view.
secureFromStingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.secure_5g_nr_sa))
secureFromStingrayTextView.text = getString(R.string.secure_from_stingray)
// Set the text color.
- secureFromStingrayTextView.setTextColor(getColor(R.color.blue_700))
+ secureFromStingrayTextView.setTextColor(getColor(R.color.blue_text))
} else { // This is not a secure 5G NR SA network.
// Populate the image view.
secureFromStingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.not_secure))
secureFromStingrayTextView.text = getString(R.string.not_secure_from_stingray)
// Set the text color.
- secureFromStingrayTextView.setTextColor(getColor(R.color.red_700))
+ secureFromStingrayTextView.setTextColor(getColor(R.color.red_text))
- // Get the strings that correspond to the network information.
- val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType)
- val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType)
+ // Get the strings that correspond to the network information.
+ val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType)
+ val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType)
- // 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]
+ // 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]
}
}
- }, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
+
+ 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]
+
+ // Get the voice network type.
+ val voiceNetworkType = getNetworkType(networkRegistrationInfo.accessNetworkTechnology)
+
+ // Populate the voice network text views.
+ voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0])
+ voiceNetworkDetailsTextView.text = voiceNetworkType[1]
+ }
+ }, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED or PhoneStateListener.LISTEN_SERVICE_STATE)
}
private fun getNetworkType(networkType: Int) : Array<String> {
// Return the string that corresponds to the network type.
return when(networkType) {
- TelephonyManager.NETWORK_TYPE_UNKNOWN -> arrayOf(getString(R.string.unknown), getString(R.string.unknown))
+ TelephonyManager.NETWORK_TYPE_UNKNOWN -> arrayOf(getString(R.string.unknown), "")
TelephonyManager.NETWORK_TYPE_GPRS -> arrayOf(getString(R.string.gprs), getString(R.string.gprs_detal))
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_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), getString(R.string.error))
+ else -> arrayOf(getString(R.string.error), "")
}
}