Interacting with the phone

In your day-to-day development you will often want to interact with the phone. This interaction may be as simple as dialing outbound calls through built-in intents, or it may involve intercepting calls to modify them in some way. In this section we are going to cover these basic tasks, and we will examine some of the phone number utilities Android provides for you out of the box.

One of the more common things you will do with the Android telephony support doesn't involve the telephony APIs directly, and that is making calls using the built-in intents.

7.3.1 Using intents to make calls

As we demonstrated in chapter 4, using the Intent.ACTION_CALL action and the tel: Uri is all you need to invoke the built-in dialer application and make a call. This approach will invoke the dialer application, populate the dialer with the provided telephone number (taken from the Uri), and initiate the call.

Along with this action you can also invoke the dialer application with the Intent.ACTION_DIAL action, which will again populate the dialer with the supplied phone number but stop short of initiating the call. Listing 7.3 demonstrates both techniques using the respective actions.

Listing 7.3 Using Intent actions to dial and call using the built-in dialer application dialintent = (Button) findViewById(R.id.dialintent_button); dialintent.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent =

new Intent (Intent. DIAL_ACTION, <-O Usage of DIALACTION

Uri. parse ("tel:" + NUMBER)); <-1 "

startActivity (intent) ; | Including the

} C tel:number Uri

callintent = (Button) findViewById(R.id.callintent_button); callintent.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent (Intent. CALL_ACTION, Uri .parse ( "tel: " + NUMBER) ) ; startActivity(intent);

At this point we have covered the usage of intents and the Android platform design quite a bit. In listing 7.3 we are once again leveraging this design, to make outgoing calls to specified numbers.

Making calls using the built-in intents through the dialer application is very simple, as we have already shown in previous examples. Basically you need to set the action you want to take place, either populating the dialer with ACTION_DIAL O or populating the dialer and initiating a call with ACTION_CALL ©. In either case you also need to specify the telephone number you want to use with the Intent Uri ©.

The only other aspect of dialing calls you need to be aware of is permissions. The correct permissions are required in your application manifest in order to be able to access and modify phone state, dial the phone, or intercept phone calls (which we will examine in section 7.3.3). Table 7.1 lists the relevant phone-related permissions and their purposes (for more detailed information see the security section of the Android documentation: http://code.google.com/android/devel/security.html).

Table 7.1 Phone-related manifest permissions and their purpose

Phone-related permission

Purpose

android.permission.READ_PHONE_STATE

android.permission.MODIFY_PHONE_STATE

android.permission.CALL_PHONE

android.permission.CALL_PRIVILEGED

android.permission.PROCESS_OUTGOING_CALLS

Allow application to read phone state

Allow application to modify phone state

Initiate a phone call without user confirmation in dialer

Call any number, including emergency, without confirmation in dialer

Allow application to receive broadcast for outgoing calls and modify

I Usage of D CALL ACTION

Dialing from an Android application is very straightforward. The built-in handling via intents and the dialer application make it almost trivial. Helping even more in terms of "making it nice for the people" is the additional PhoneNumberUtils class, which you can use to parse and validate phone number strings.

7.3.2 Helpful phone number-related utilities

Applications running on mobile devices that support telephony get to experience the joy of dealing with a good deal of String formatting for phone numbers. Fortunately, in the Android SDK there is a handy utility class that helps to mitigate the risks associated with this task and standardize the way it's done—PhoneNumberUtils.

The PhoneNumberUtils class can be used to parse String data into phone numbers, parse alphabetical keypad digits into numbers, and determine other properties of phone numbers (such as whether or not they are global or localized). An example usage of this class is shown in listing 7.4.

Listing 7.4 Working with the PhoneNumberUtils class private TextView pnOutput; private EditText pnlnput; private EditText pnlnPlacelnput; private Button pnFormat;

this.pnFormat.setOnClickListener (new OnClickListener() {

public void onClick(view v) { Format as

String phoneNumber = PhoneNumberUtils . formatNumber ( | phone number pnlnput. getText () . toString () ) ; <1-'

phoneNumber = PhoneNumberUtils.convertKeypadLettersToDigits(

| Convert alpha

StringBuilder result = new StringBuilder () ; © characters to digits result.append(phoneNumber); result.append("\nisGlobal - "

+ PhoneNumberUtils.isGlobalPhoneNumber(phoneNumber)); result.append("\nisEmergency - "

+ PhoneNumberUtils.isEmergencyNumber(phoneNumber));

, Use additional phone pnInput setText(""); number utilities D

The PhoneNumberUtils class has a number of static helper methods for parsing phone numbers, the simplest of which is formatNumber. This method takes a single String as input and uses the default locale settings to return a formatted phone number O (there are additional methods to format a number using a locale you specify, to parse different segments of a number, and so on). Parsing a number can be combined with another helpful method, convertKeypadLettersToDigits, to further convert any alphabetic keypad letter characters into digits C. The conversion method won't work unless it already recognizes the format of a phone number, so in this case it's important to run the format method first.

Along with these basic methods you can also check properties of a number string, such as whether the number is global and whether it represents an emergency call ©.

An additional way to format a phone number that is useful for any Editable, such as the very common EditText (or TextView), is the formatNumber overload that edits these in place. This method updates an EditText that is passed in when it is invoked. An example of using this is shown in listing 7.5.

Listing 7.5 Using in-place Editable View formatting via PhoneNumberUtils this.pnInPlaceInput.setOnFocusChangeListener( O Use OnF°cusChangeListener new OnFocusChangeListener () { <1-I for update public void onFocusChange(View v, boolean b) {

if (v.equals(pnlnPlacelnput) && (b == false)) { PhoneNumberUtils.formatNumber( pnlnPlacelnput. getText () , © Cal1 formatNumber PhoneNumberUtils . FORMAT_NANP) ; <-1 method

The in-place editor can be combined with a dynamic update step using various techniques; one way is to make the update happen automatically when the focus changes away from a phone number field (curiously though, the in-place edit does not also provide the keypad alphabetic character-to-number conversion automatically). To do this we have implemented an OnFocusChangeListener O. Inside the onFocusChange method, which filters for the correct View item, we call the formatNumber overload, passing in the respective Editable and the formatting style we want to use . The NANP here stands for North American Numbering Plan, which includes an optional country and area code and a seven-digit phone number.

Apart from using the phone number utilities and making calls, you may also need to intercept calls.

7.3.3 Intercepting calls

There are many reasons you may want to intercept calls. For example, you may want to write an application that is aware of incoming phone calls and changes the ringer or uses other different alerts based on the caller. In addition, you may want to write an application that catches outgoing calls and decorates or aborts them, based on certain criteria.

Intercepting outgoing calls is supported in the current Android SDK release, but unfortunately the same is not true of incoming calls. Currently incoming calls cannot be intercepted. Users can still change the ringer and other options for their contacts, but all of that is based on the built-in applications and is not something that's available to you as a developer through the APIs.

Because of the limitations in the API, we will focus on what an intercept for an outgoing call looks like, which is shown in listing 7.6.

Listing 7.6 Catching and aborting an outgoing call public class OutgoingCallReceiver extends BroadcastReceiver { <1-1 Create public static final String ABORT_PHONE_NUMBER = "1231231234"; I broadcast

O receiver private static final String OUTGOING_CALL_ACTION =

"android, intent. action.NEW_OUTGOING_CALL" ; <-1 Define constant for private static final String INTENT_PHONE_NUMBER = © NEW OUTGOING CALL "android, intent. extra . PHONE NUMBER"; <1-^-=—

, , . , . s . | Override public void onReceive (Context context, Intent intent) { Q onReceive if (intent.getAction().equals( OutgoingCallReceiver . OUTGOING_CALL_ACTION)) <—i

String phoneNumber = Filter Intent for action Q

intent. getExtras () . getString (INTENT_PHONE_NUMBER) ; <—, if ((phoneNumber i = null) Get Intent extras data Q

&& phoneNumber.equals( OutgoingCallReceiver . ABORT_PHONE_NUMBER) ) { Toast. makeText (context, Define constant for

"NEW_OUTGOING_CALL intercepted to number " + "123-123-1234 - aborting call",

Toas t. LENGTH_LONG) .show () ; <-1 Show this . abortBroadcast () ; <—i | quick

PHONE_NUMBER Q

} Abort Intent

The first thing we do to intercept an outgoing call is to extend BroadcastReceiver O. Our receiver defines several constants, one for the NEW_OUTGOING_CALL action © and one for the phone number data key, PHONE_NUMBER Q.

For a BroadcastReceiver we have to implement the onReceive method Q. Within this method we filter on the Intent action we want, android.intent. action.NEW_OUTGOING_CALL Q, then we get the Intent data using the phone number key ©. If the phone number matches, we send a Toast alert to the UI O and abort the outgoing call by calling the abortBroadcast method ©.

Beyond dialing out, formatting numbers, and intercepting calls, another important area of the telephony support in Android is the support for sending and receiving SMS.

+1 0

Responses

  • sigismond
    What can be used in place of setonfocuschangelistener?
    7 years ago
  • Jodi
    How to dial a call in android using telephony apis?
    7 years ago
  • edna
    How to intercept phone calls in android by code?
    9 months ago

Post a comment