Previous section   Next section

Mobile Phone Handheld Hardware Hardware Rick Rogers John Lombardo O'Reilly Media, Inc. O'Reilly Media Android Application Development, 1st Edition

14.2. Exploring the Phone Code Through the Debugger

We 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.

Figure 14-3. Eclipse debugger stopped in call method


14.2.1. Creating an Instance of an Intent

The 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 Intent

So 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 Call

The 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.

          
      Previous section   Next section