Accessing telephony information

Android provides a very informative manager class that supplies information about many telephony-related details on the device. Using this class, TelephonyManager, you can access many of the GSM/SIM properties we have already discussed, and you can obtain phone network state information and updates.

Attaching an event listener to the phone, in the form of a PhoneStateListener, which is done via the manager, is how you can make your applications aware of when phone service is and is not available and when calls are started, in progress, or ending, and more.

Here we are going to examine several parts of the TelephonyExplorer example application to look at both of these classes and concepts, starting with obtaining a TelephonyManager instance and using it to query useful telephony information.

7.2.1 Retrieving telephony properties

The android.telephony package contains the TelephonyManager class, and it has details on all of the information you can obtain using it. Here we are going to get and display a small subset of that information to demonstrate the approach. The first Activity, beyond the main screen, our TelephonyExplorer application will have is a simple screen that shows some of the information we can obtain via TelephonyManager, as shown in figure 7.2.

TelExplore

Telephony Manager Information:

TelExplore

Telephony Manager Information:

te I Mgr • callState = IDLE œlILocatlonString = -1 -1 devlceld = OOQOQOOOOOCOOOO devlceSoftwareVerslon = null llnelMumber = 15555218135 networkCountrylso = us networkOperator - 310260 networiOperatorHame = Android plloneTypeStrlng = GSM slmCountrylso = us slmOperator = 310260 slmOperatorName - Android slmSerlalNumber = S9014103211118510720 slmSubscrlberld = 310260Û0Û000000 slmStateStrlng = 5TATEREA0Y

Figure 7.2 Displaying device and phone network metainformation obtained from the TelephonyManager class

The TelephonyManager class is the information hub for telephony-related data in Android. Listing 7.1 demonstrates how you obtain a reference to this class and use it to retrieve data (such as the data shown in figure 7.2).

Listing 7.1 Obtaining a TelephonyManager reference and using it to retrieve data

// . . . start of class omitted for brevity final TelephonyManager telMgr =

(TelephonyManager) this . getSystemService ( O Get TelephonyManager

Context. TELEPHONY_SERVICE) ; <1-I from Context

// . . . onCreate method and others omitted for brevity public String getTelephonyOverview ( © lmp|ement information TelephonyManager telMgr) { <-I he|per meth°d int callState = telMgr.getCallState () ; <1-1 Obtain call state

String callStateString = "NA" ; © information switch (callState) {

case TelephonyManager. CALL_STATE_IDLE : callStateString = "IDLE"; break;

case TelephonyManager. CALL_STATE_OFFHOOK: callStateString = "OFFHOOK"; break;

case TelephonyManager. CALL_STATE_RINGING: callStateString = "RINGING"; break;

GsmCellLocation cellLocation =

(GsmCellLocation) telMgr.getCellLocation ( );

String cellLocationString =

cellLocation.getLac() + " " + cellLocation.getCid();

String deviceld = telMgr.getDeviceld() ; | ^ get cell location

String deviceSoftwareVersion = ^ information telMgr.getDeviceSoftwareVersion();

String linelNumber = telMgr.getLinelNumber(); <-

String networkCountrylso = telMgr.getNetworkCountrylso();

String networkOperator = telMgr.getNetworkOperator();

String networkOperatorName = telMgr.getNetworkOperatorName();

int phoneType = telMgr. getPhoneType () ; get device

String phoneTypeString = "NA"; information ©

switch (phoneType) {

case TelephonyManager. PHONE_TYPE_GSM: phoneTypeString = "GSM"; break;

case TelephonyManager . PHONE_TYPE_NONE: phoneTypeString = "NONE"; break;

String simCountryIso = telMgr.getSimCountryIso(); String simOperator = telMgr.getSimOperator(); String simOperatorName = telMgr.getSimOperatorName(); String simSerialNumber = telMgr.getSimSerialNumber(); String simSubscriberId = telMgr.getSubscriberId(); int simState = telMgr.getSimState(); String simStateString = "NA";

case TelephonyManager . SIM_STATE_ABSENT: © information simStateString = "ABSENT"; break;

case TelephonyManager . SIM_STATE_NETWORK_LOCKED: simStateString = "NETWORK_LOCKED"; break;

StringBuilder sb = new StringBuilder(); sb.append("telMgr - ");

sb.append(" \ncallState = " + callStateString); // . . . remainder of appends omitted for brevity return sb.toString();

The Android Context is used, through the getSystemService method with a constant, to obtain an instance of the TelephonyManager class O. Once you have a handle to the manager, you can use it as needed to obtain information. In this case we have created a helper method to get data from the manager and return it as a String we later display on the screen ©.

The manager allows you to access phone state data, such as whether or not a call is in progress ©, cell location information ©, the device ID and software version ©, the phone number registered to the current user/SIM ©, and many other SIM details such as the subscriber ID (IMSI) H. There are additional properties that we are not using in this example (see the Javadocs for complete details).

Note one more detail here not shown in the listing. In order for this class to work, the READ_PHONE_STATE permission has to be set in the manifest (without it security exceptions will be thrown when you try to read data from the manager). We have consolidated the phone-related permissions into table 7.1, in section 7.3.1.

This handle to the telephony-related information, including metadata about the device, network, and SIM card, is one of the main purposes of the TelephonyManager class. The other main purpose of TelephonyManager is to allow you to attach a PhoneStateListener.

7.2.2 Obtaining phone state information

Obviously a phone has various states that it as a device can be in. The most basic phone states are idle, in a call, or in the process of initiating a call. When building applications on a mobile device, there are times when you not only need to know the current phone state but also want to be alerted anytime the state changes.

© Get cellGet / phone number of device location information

In these cases you want to attach a listener to the phone and "subscribe" so that you can be notified of "published" changes. With Android this is done using a PhoneState-Listener, which is attached to the phone through TelephonyManager. Listing 7.2 demonstrates a sample usage of both of these classes.

Listing 7.2 Attaching a PhoneStateListener via the TelephonyManager

@Override public void onStart() { super.onStart();

final TelephonyManager telMgr = (TelephonyManage r)

this .getSystemService ( O Obtain TelephonyManager

Context. TELEPHONY_SERVICE) ; <-1 from Context

PhoneStateListener phoneStateListener = Create

PhoneStateListener new PhoneStateListener() { public void onCallStateChanged(

int state, String incomingNumber) { <1-

telMgrOutput.setText(getTelephonyOverview(telMgr));

. . . onCallStateChanged method D

telMgr.listen(phoneStateListener, °

PhoneStateListener . LISTEN_CALL_STATE) ; <1-

String telephonyOverview = this.getTelephonyOverview(telMgr); this.telMgrOutput.setText(telephonyOverview);

} Assign listener to manager O

To start working with a PhoneStateListener you need an instance of TelephonyManager, so you can later assign the listener O. PhoneStateListener itself is an interface, so you need to create an implementation ©, including the onCallStateChanged required method, in order to use it ©. Once you have a PhoneStateListener instance (your own implementation that implements the interface), you attach it by assigning it to the manager with the listen method ©.

In the example in listing 7.2 we are listening for any PhoneStateListener. LISTEN_CALL_STATE change in the phone state. This is a constant value from a list of available states that can be seen on the PhoneStateListener class. You can use a single value when assigning a listener with the listen method, as we have done here, or you can combine multiple values.

If a call state change does occur, we reset the details on the screen using the getTelephonyOverview method we used for setting the initial status in listing 7.1. The action you take is defined in the onCallStateChanged method of your PhoneStateListener. You can filter further in this method too (apart from the types of events you are listening for), based on the passed-in int state, if you need to.

To see the values in this example change while working with the emulator, you can use the SDK tools to send incoming calls or text messages and change the state of the voice connection. The emulator includes a mock GSM modem that you can manipulate using the gsm command from the console. Figure 7.3 shows an example session from the

ccollinsgcrotaluWopt/android/toolsS telnet localhost 5554 Trying 127,8.6,1... Connected to localhost. Escape character is ■*]1.

Android Console: type 'help' for a list of commands

gsra allows you to change GSM-related settings, or to make a new inbound phone call available sub - commands:

list list current phone calls call create inbound phone call busy close waiting outbound call as busy hold change the state of an oubtound call to 'held1

accept change the state of an outbound call to 'active'

cancel disconnect an inbound or outbound phone call data modify [fata connection state voice modify voice connection state status display GSM status

Figure 7.3 An Android console session demonstrating the gsm command and available subcommands console that demonstrates this. For complete details see the emulator telephony documentation (http://code.google.com/android/reference/emulator.html - telephony).

With many of the larger telephony background details now complete, in the next few sections of this chapter we're going to cover basic uses of the telephony APIs and other related facilities. We will examine intercepting calls, using some of the telephony utility classes, and making calls from your applications.

0 0

Post a comment