Unfortunately, you can't rely on the APIs for many of these cases.
The only method I found is to register a listener to get the ServiceState
from the TelephonyManager and then parse the result of serviceState.toString()
telephonyManager.listen(object : PhoneStateListener() {
override fun onServiceStateChanged(state: ServiceState) {
val serviceState = state.toString()
val nr = serviceState.isNrAvailable()
...
}
}, PhoneStateListener.LISTEN_SERVICE_STATE)
fun String.isNrAvailable() =
contains("nrState=CONNECTED") ||
contains("nsaState=5"))
This gives you the correct answer most
of the times. BTW NR NSA
is the correct name for NR non-standalone.
If you want to distinguish between NRSA and NRNSA you need to fetch all the cellInfo from the TelephonyManager
telephonyManager.allCellInfo
and check whether the primary cell is NR.
cellInfo.cellConnectionStatus
In some cases what you will see is that there are no NR cells. In that case, you can be sure that the connection is NRNSA (assuming that it is 5G).
In other cases, there will be NR cells but they won't be reported as primary-cell. It is possible that the device will even report the NR cell as not connected at all even if it is used. Again in that case you know it is NRNSA.
You might detect the NR cell that is used even if it is reported as not connected by checking the strengths.
cellInfo.cellSignalStrength.dbm
You will see that the strength reported is the same as the strength of the NR cell with the highest SS-RSRP (Synchronization Signal Reference Signal Received Power)
I would avoid using the TelephonyDisplayInfo
since it is not reliable. These values are shown to the users and they follow the carrier policy or brand preferences.