Mobile Phone Handheld Hardware Hardware Rick Rogers John Lombardo O'Reilly Media, Inc. O'Reilly Media Android Application Development, 1st Edition15.1. Operations Offered by the android.telephony PackageThe android.telephony package contains a set of classes that can be used by any
application in the Android environment to monitor the state of Android's
mobile network connection. It also contains classes for locating a device
using the mobile network. Finally, it offers utility classes for parsing,
formatting, and otherwise managing phone numbers, although there is no
architectural benefit to locating those classes in this package. The telephony package does not allow you to place, end, or otherwise
meddle in phone calls; it focuses on retrieving information and giving
users an interface to edit telephone numbers. We'll explain later why
Android reserves the actual control over phone calls to PhoneApp. 15.1.1. Package SummaryThe android.telephony package contains the
following packages:
CellLocation Methods to request location information.
PhoneNumberFormattingTextWatcher Callback methods that notify an application about changes to
phone numbers themselves. When used with a TextView object, it formats the text as
a phone number using methods in the PhoneNumberUtils class.
PhoneNumberUtils A utility class that contains methods for processing
strings containing phone numbers.
PhoneStateListener Callback methods that track changes in the state of the
mobile network connection, the call, or other telephony
objects.
ServiceState Methods that return information about the current mobile
network service provider and the availability of service.
TelephonyManager Methods that provide information about the state of mobile
service, the call state, the SIM, the network, the subscriber to
the mobile service, voicemail, and other related
information.
Because these classes don't control hardware or change state
information about phone calls, they don't have any access
control. 15.1.2. Limitations on What Applications Can Do with the PhoneSome readers may be disappointed to see that the
android.telephony package limits their access to
getting information, and does not provide direct control over the dialer
or the state of a call. There are good reasons for this. Essentially,
providing a low-level telephony API that can be shared among multiple
applications is perilous. A mobile handset is a state machine that keeps track of the mobile
radio reports, provides audible call state indications to the user, and
enables the user to provide inputs that modify that state. Even if you
could design an API that would, hypothetically, share a mobile radio
among multiple applications on a per-call basis, the user interface and
ergonomic design that would go along with shared control among multiple
applications would be difficult and probably even intractable. A phone
is not like a PC with a desktop user interface: you can't share control
over the parts of a device that constitute the phone the way you can
share the screen of a PC. Android provides a workable solution that keeps telephony usable
while making as much of the system open to your applications as is
practicable. As we saw in the previous chapter, PhoneApp exposes an
Intent that lets other applications initiate phone calls, while enabling
a single application to control the mobile radio in an Android handset.
The android.telephony package further exposes
information about telephone service and the calls made by an
application. It's useful to think of telephony on Android as an interface that
keeps critical functions private while providing public APIs for
functions where it is safe to do so. This is a good example of a
successful Android design strategy. 15.1.3. Example: Determining the State of a CallThis section shows how to track the state of a phone call. It adds
some of the classes described in the previous section to the application
shown in Section 14.1.1, which
finds and uses PhoneApp to start and control a phone call. Here, in
addition to starting a phone call and letting PhoneApp control it, the
application gets some information about the call as it is happening. In order to get this information, we need to extend the PhoneStateListener class, make an instance of
our subclass, and pass that instance to the TelephonyManager.listen method. Example 15-1 shows the code for our subclass
of the PhoneStateListener
class. Example 15-1. Defining a Listener for telephone call stateprivate class ListenToPhoneState extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
Log.i("telephony-example", "State changed: " + stateName(state));
}
String stateName(int state) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: return "Idle";
case TelephonyManager.CALL_STATE_OFFHOOK: return "Off hook";
case TelephonyManager.CALL_STATE_RINGING: return "Ringing";
}
return Integer.toString(state);
}
}
|
The lines we've highlighted are: In this subclass of the PhoneStateListener class, we override the
onCallStateChanged method, which
Android calls when a call's state changes. We use the Log class, a static class with utility methods
for logging information, to log the changes as Android passes them to
us. Finally, our stateName method
decodes the states that correspond to the constants defined in the
TelephonyManager class to make the log more
readable. Returning to our main application from Section 14.1.1, we have to change it by
creating a Listener and assigning our subclass of PhoneStateListener to it. Here is the code for
the entire modified example application, which now tracks and logs state
transitions: package example.telephony;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;<-- (1)
import android.util.Log;
public class telephonyExplorer extends Activity {
ListenToPhoneState listener;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
call();
}
private void call() {
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:9785551212"));
startActivity(callIntent);
TelephonyManager tManager = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
listener = new ListenToPhoneState();
tManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
} catch (ActivityNotFoundException activityException) {
Log.e("telephony-example", "Call failed", activityException);
}
}
private class ListenToPhoneState extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
Log.i("telephony-example", "State changed: " + stateName(state));
}
String stateName(int state) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: return "Idle";
case TelephonyManager.CALL_STATE_OFFHOOK: return "Off hook";
case TelephonyManager.CALL_STATE_RINGING: return "Ringing";
}
return Integer.toString(state);
}
}
}
The lines we've highlighted are: Running this application results in output to the log window in
Eclipse that should look something like this: 11-19 01:47:03.704: INFO/telephony-example(159): State changed: Idle
11-19 01:47:04.774: INFO/telephony-example(159): State changed: Off hook
 |