Interview Questions

Using Android Telephony APIs

Although the Android platform has been designed to run on almost any type of device, the Android devices available on the market are primarily phones. Applications can take advantage of this fact by integrating phone features into their feature set.

This chapter introduces you to the telephony-related APIs available within the Android SDK.

Working with Telephony Utilities

The Android SDK provides a number of useful utilities for applications to integrate phone features available on the device. Generally speaking, developers should consider an Android device first and foremost as a phone. Although these devices might also run applications, phone operations generally take precedence. Your application should not interrupt a phone conversation, for example. To avoid this kind of behavior, your application should know something about what the user is doing, so that it can react differently. For instance, an application might query the state of the phone and determine that the user is talking on the phone and then choose to vibrate instead of play an alarm.

In other cases, applications might need to place a call or send a text message. Phones typically support a Short Message Service (SMS), which is popular for texting (text messaging). Enabling the capability to leverage this feature from an application can enhance the appeal of the application and add features that can’t be easily replicated on a desktop environment. Because many Android devices are phones, applications frequently deal with phone numbers and the contacts database; some might want to access the phone dialer to place calls or check phone status information. Adding telephony features to an application enables a more integrated user experience and enhances the overall value of the application to the users.

Gaining Permission to Access Phone State Information

Let’s begin by looking at how to determine telephony state of the device, including the ability to request the hook state of the phone, information of the phone service, and utilities for handling and verifying phone numbers. The TelephonyManager object within the android.telephony package is a great place to start.

Many of the method calls in this section require explicit permission set with the Android application manifest file. The READ_PHONE_STATE permission is required to retrieve information such as the call state, handset phone number, and device identifiers or serial numbers. The ACCESS_COARSE_LOCATION permission is required for cellular location information. Recall that we cover location-based services in detail in Chapter “Using Location- Based Services (LBS) APIs.”

The following block of XML is typically needed in your application’s AndroidManifest.xml file to access basic phone state information:

<uses-permission
android:name=”android.permission.READ_PHONE_STATE” />

Requesting Call State

You can use the TelephonyManager object to retrieve the state of the phone and some information about the phone service itself, such as the phone number of the handset.

You can request an instance of TelephonyManager using the getSystemService() method, like this:

  TelephonyManager telManager = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);

With a valid TelephonyManager instance, an application can now make several queries.One important method is getCallState().This method can determine the voice call status of the handset. The following block of code shows how to query for the call state and all the possible return values:

  int callStatus = telManager.getCallState();
String callState = null;
switch (callStatus) {
case TelephonyManager.CALL_STATE_IDLE:
callState = “Phone is idle.”;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
callState = “Phone is in use.”;
break;
case TelephonyManager.CALL_STATE_RINGING:
callState = “Phone is ringing!”;
break;
}
Log.i(“telephony”, callState);

The three call states can be simulated with the emulator through the Dalvik Debug Monitor

Querying for the call state can be useful in certain circumstances. However, listening for changes in the call state can enable an application to react appropriately to something the user might be doing. For instance, a game might automatically pause and save state information when the phone rings so that the user can safely answer the call. An application can register to listen for changes in the call state by making a call to the listen() method of TelephonyManager.

  telManager.listen(new PhoneStateListener() {
public void onCallStateChanged(
int state, String incomingNumber) {
String newState = getCallStateString(state);
if (state == TelephonyManager.CALL_STATE_RINGING) {
Log.i(“telephony”, newState +
“ number = “ + incomingNumber);
} else {
Log.i(“telephony”, newState);
}
}
}, PhoneStateListener.LISTEN_CALL_STATE);

The listener is called, in this case, whenever the phone starts ringing, the user makes a call, the user answers a call, or a call is disconnected. The listener is also called right after it is assigned so an application can get the initial state.

Another useful state of the phone is determining the state of the service. This information can tell an application if the phone has coverage at all, if it can only make emergency calls, or if the radio for phone calls is turned off as it might be when in airplane mode. To do this, an application can add the Phone State Listener .LISTEN_ SERVICE_STATE flag to the listener described earlier and implement the onServiceStateChanged method, which receives an instance of the ServiceState object. Alternatively, an application can check the state by constructing a ServiceState object and querying it directly, as shown here:

  int serviceStatus = serviceState.getState();
String serviceStateString = null;
switch (serviceStatus) {
case ServiceState.STATE_EMERGENCY_ONLY:
serviceStateString = “Emergency calls only”;
break;
case ServiceState.STATE_IN_SERVICE:
serviceStateString = “Normal service”;
break;
case ServiceState.STATE_OUT_OF_SERVICE:
serviceStateString = “No service available”;
break;
case ServiceState.STATE_POWER_OFF:
serviceStateString = “Telephony radio is off”;
break;
}
Log.i(“telephony”, serviceStateString);

In addition, a status such as whether the handset is roaming can be determined by a call to the getRoaming() method. A friendly and frugal application can use this method to warn the user before performing any costly roaming operations such as data transfers within the application.

Requesting Service Information

In addition to call and service state information, your application can retrieve other information about the device. This information is less useful for the typical application but can diagnose problems or provide specialized services available only from certain provider networks. The following code retrieves several pieces of service information:

  String opName = telManager.getNetworkOperatorName();
Log.i(“telephony”, “operator name = “ + opName);
String phoneNumber = telManager.getLine1Number();
Log.i(“telephony”, “phone number = “ + phoneNumber);
String providerName = telManager.getSimOperatorName();
Log.i(“telephony”, “provider name = “ + providerName);

The network operator name is the descriptive name of the current provider that the handset connects to. This is typically the current tower operator. The SIM operator name is typically the name of the provider that the user is subscribed to for service. The phone number for this application programming interface (API) is defined as the MSISDN, typically the directory number of a GSM handset (that is, the number someone would dial to reach that particular phone).

Monitoring Signal Strength and Data Connection Speed

Sometimes an application might want to alter its behavior based upon the signal strength or service type of the device. For example, a high-bandwidth application might alter stream quality or buffer size based on whether the device has a low-speed connection (such as 1xRTT or EDGE) or a high-speed connection (such as EVDO or HSDPA). TelephonyManager can be used to determine such information.

If your application needs to react to changes in telephony state, you can use the listen() method of TelephonyManager and implement a PhoneStateListener to receive changes in service, data connectivity, call state, signal strength, and other phone state information.

Working with Phone Numbers

Applications that deal with telephony, or even just contacts, frequently have to deal with the input, verification, and usage of phone numbers. The Android SDK includes a set of helpful utility functions that simplify handling of phone number strings. Applications can have phone numbers formatted based on the current locale setting. For example, the following code uses the formatNumber() method:

  String formattedNumber =
PhoneNumberUtils.formatNumber(“9995551212”);
Log.i(“telephony”, formattedNumber);

The resulting output to the log would be the string 999-555-1212 in my locale. Phone numbers can also be compared using a call to the PhoneNumberUtils.compare() method. An application can also check to see if a given phone number is an emergency phone number by calling PhoneNumberUtils.isEmergencyNumber(), which enables your application to warn users before they call an emergency number. This method is useful when the source of the phone number data might be questionable.

The formatNumber() method can also take an Editable as a parameter to format a number in place. The useful feature here is that you can assign the Phone Number Formatting TextWatcher object to watch a TextView (or EditText for user input) and format phone numbers as they are entered. The following code demonstrates the ease of configuring an EditText to format phone numbers that are entered:

  EditText numberEntry = (EditText) findViewById(R.id.number_entry);
numberEntry.addTextChangedListener(
new PhoneNumberFormattingTextWatcher());

While the user is typing in a valid phone number, the number is formatted in a way suitable for the current locale. Just the numbers for 19995551212 were entered on the EditText shown in Figure.


Pragna Meter
Next Chapter  
e-University Search
Related Jobs