Mobile Phone Handheld Hardware Hardware Rick Rogers John Lombardo O'Reilly Media, Inc. O'Reilly Media Android Application Development, 1st Edition14.2. Exploring the Phone Code Through the DebuggerWe will use the Eclipse debugger, set breakpoints, and inspect class members in the
running application to observe what is going on inside this example. The
use of the debugger with Android is described in Chapter 5. If you have not used a debugger before,
don't worry: we will use a limited set of debugging capabilities here to
observe a program that works correctly. Just follow the steps in this
section and let the debugger show you what is happening. First, we will set a breakpoint where we want to start observing
what is happening inside the application. To set a breakpoint,
double-click on the left margin of the view that shows the program code in
Eclipse. A blue dot will appear. If you change your mind and decide not to
insert a breakpoint, double-click again on the blue dot, and it will
disappear. All we want is to stop execution of the program at the point where
we want to start inspecting what happens to the members of this instance
of the dialing class. To do this, set a
breakpoint on line 21 of the program. You can tell which line you are on
by clicking a line in the program. In the status bar at the bottom of the
Eclipse window, you will see two numbers separated by a colon. The first
number is the line number where you just clicked, and the second number is
the character position on that line where the insertion point is right
now. Start the application with the debugger by selecting Run Debug,
and when the "Debug as" dialog
appears, select Android Application. The program will stop at the breakpoint, after the Android emulator
appears on your screen but before the appearance of the dialer shown in
Figure 14-2. Eclipse will switch to a
debug perspective: a set of views configured for debugging a program instead of
editing it. Eclipse will ask if you want to switch perspectives the first
time you run the debugger; you can save your answer if you want Eclipse to
do the same thing each time you start debugging. In the debug perspective, the view displaying the program code will
show a small arrow overlapping the blue dot in the left margin. This line
of code will be highlighted. The program has stopped before executing the
Java bytecodes corresponding to the Java source code on this line of the
program. Figure 14-3 shows the Eclipse
window in debug perspective with contents similar to those that should
appear on your screen. The main information to look for is that the
program stopped executing on the line where you set the breakpoint. 
14.2.1. Creating an Instance of an IntentThe line of code where the program stopped in the previous section looks like
this: Intent callIntent = new Intent(Intent.ACTION_CALL); This creates an instance of the Intent class. Use the "step over" command to
execute this line, by selecting the Run Step Over option from the menu
or any of the shortcuts available in Eclipse. NOTE "Step over" does not mean "skip." Instead, it tells the debugger
to run the entire line of code and all the method calls it contains
(the Intent constructor, in this case) instead of entering the method
calls and going through them line by line. It isn't useful to see the
internals of the Intent constructor. So "step over" creates the Intent
and presents you with the next line of your own code. The debugger also has commands for "stepping into" methods and
"stepping out" of the method currently being executed. These commands
are more convenient than setting more breakpoints and using the Resume
command. Now that we have used the new
operator and the Intent constructor with an argument that specifies we
want to initialize the Intent with the Intent.ACTION_CALL
constant, we have an instance of the Intent class. The action we use, ACTION_CALL, will enable Android to find
PhoneApp or any other program the user may install that offers the
ACTION_CALL action. Let's take a look inside by entering the Variables view in
Eclipse. You will see two columns in this view. The first column shows
the names of the variables, and the second column shows their values. In
our case, the names refer to instances of classes, and the values
consist of the class name and the ID of the instance. That's not very informative! Let's look inside these instances and
see what they contain. Click on the triangle icon in the left margin
next to the variable named callIntent. Now you see all the members of the
Intent class and the values for this
instance of the Intent class. The
only member that has a nondefault value is mAction. Its value is the string "android.intent.action.CALL". This is the
result of calling the Intent class's
constructor with the argument we used. 14.2.2. Adding Data to an Instance of an IntentSo far, our instance of the Intent class has enough information to tell
the Android system we want to start a phone call, but not enough to tell
it what number to call. After creating the Intent instance with the information that means
"we want to call a number," in the next line we will add to it the
number to call: callIntent.setData(Uri.parse("tel:9785551212"));Two things happen on this line of code: an instance of a Uri is created, and we use that instance as an
argument to the setData method of the
Intent class. Step over this line of
code, and then let's see what happens to the variables we are
inspecting. Look at the Variable view in Eclipse and you will see that the
mData member of this instance of the Intent now refers to the instance of Uri that was returned from the parse method of
the Uri class. And if you click on
the triangle icon next to "mData", you will see the members of the
Uri class, including the uriString member that refers to the string
tel:9785551212. Now our instance of the Intent class contains all the information we
need to start a phone call. Why use a URI? All mobile numbers conform to the E.164 standard,
so why not use a String object containing a valid
E.164 number? A URI has the advantage of generality. All parts of
Android are replaceable and the components of Android that handle this
particular Intent object could be augmented or
replaced by a module that can also connect VoIP calls with SIP URIs or
Gmail addresses. 14.2.3. Initiating a Phone CallThe next line in our program looks like this: startActivity(callIntent); This looks like we want to start an Activity, using the Intent object we created. But why don't we
need to specify an instance, or even a class, when we call startActivity? Because our program is
an instance of the Activity class. We are calling a
method of the class this object is an instance of. We could have used
the following instead: this.startActivity(callIntent); Our program is already an Activity, but we now want to start a new
instance of the Activity class—one
that can handle the Intent instance
we created. The Android framework handles the call by searching for an
Intent that matches our request for ACTION_CALL. Let's step over this line and see
what happens. Now the arrow in the left margin of the code view points to the
last line of the call method, just before the method returns. The
emulator window shows the Android call status application displaying the
number we specified. It should look like Figure 14-2, shown earlier in this
chapter. The fact that we stepped over this line of code and can now
continue executing our program means that making a phone call this way
is asynchronous: it allows our program to continue running while the
dialer program makes the phone call. Android is a collection of applications, and the application you
are debugging places no restrictions on other applications that can be
running at the same time.
|