311 311 Chapter Handling Telephone Calls Many, if not most, Android devices will be phones. As such, not only will users be expecting to place and receive calls using Android, but you will have the opportunity to help them place calls, if you wish. Why might you want to? Maybe you are writing an Android interface to a sales management application (a la Salesforce.com) and you want to offer users the ability to call prospects with a single button click, and without them needing to keep those contacts both in your application and in the phone’s contacts application. Maybe you are writing a social networking application, and the roster of phone numbers that you can access shifts constantly, so rather than try to synchronize the social network contacts with the phone’s contact database, you let people place calls directly from your application. Maybe you are creating an alternative interface to the existing contacts system, perhaps for users with reduced motor control (e.g., the elderly), sporting big buttons and the like to make it easier for them to place calls. Whatever the reason, Android has the means to let you manipulate the phone just like any other piece of the Android system. Report to the Manager To get at much of the phone API, you use the TelephonyManager. That class lets you do things like the following: Determine if the phone is in use via getCallState(), with return values of CALL_STATE_IDLE (phone not in use), CALL_STATE_RINGING (call requested but still being connected), and CALL_STATE_OFFHOOK (call in progress). 34 CHAPTER 34: Handling Telephone Calls 312 Find out the SIM ID (IMSI) via getSubscriberId(). Find out the phone type (e.g., GSM) via getPhoneType(), or find out the data connection type (e.g., GPRS or EDGE) via getNetworkType(). You Make the Call! You can also initiate a call from your application, such as from a phone number you obtained through your own web service. To do this, simply craft an ACTION_DIAL Intent with a Uri of the form tel:NNNNN (where NNNNN is the phone number to dial) and use that Intent with startActivity(). This will not actually dial the phone; rather, it activates the dialer activity, from which the user can press a button to place the call. For example, let’s look at the Phone/Dialer sample application. Here’s the crude (but effective) layout: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Number to dial:" /> <EditText android:id="@+id/number" android:layout_width="fill_parent" android:layout_height="wrap_content" android:cursorVisible="true" android:editable="true" android:singleLine="true" /> </LinearLayout> <Button android:id="@+id/dial" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="Dial It!" /> </LinearLayout> We have a labeled field for typing in a phone number, plus a button for dialing that number. The Java code simply launches the dialer using the phone number from the field: CHAPTER 34: Handling Telephone Calls 313 package com.commonsware.android.dialer; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; public class DialerDemo extends Activity { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); final EditText number=(EditText)findViewById(R.id.number); Button dial=(Button)findViewById(R.id.dial); dial.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { String toDial="tel:"+number.getText().toString(); startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(toDial))); } }); } } The activity’s own UI is not that impressive, as you can see in Figure 34–1. Figure 34–1. The DialerDemo sample application, as initially launched CHAPTER 34: Handling Telephone Calls 314 However, the dialer you get from clicking the dial button is better, showing you the number you are about to dial, as shown in Figure 34–2. Figure 34–2. The Android Dialer activity, as launched from DialerDemo 315 315 Chapter Development Tools The Android SDK is more than a library of Java classes and API calls. It also includes a number of tools to assist in application development. Much of the focus has been on the Eclipse plug-in, to integrate Android development with that IDE. Secondary emphasis has been placed on the plug-in’s equivalents for use in other IDEs or without an IDE, such as adb for communicating with a running emulator. This chapter will cover other tools beyond those two groups. Hierarchical Management Android comes with a Hierarchy Viewer tool, designed to help you visualize your layouts as they are seen in a running activity in a running emulator. So, for example, you can determine how much space a certain widget is taking up, or try to find where a widget that does not appear on the screen is hiding. To use Hierarchy Viewer, you first need to fire up your emulator, install your application, launch your activity, and navigate to spot you wish to examine. Note that you cannot use Hierarchy Viewer with a production Android device (e.g., T-Mobile G1). For illustration purposes, we’ll use the ReadWrite demo application introduced back in Chapter 23, as shown in Figure 35–1. You can launch Hierarchy Viewer via the hierarchyviewer program, found in the tools/ directory in your Android SDK installation. This brings up the main Hierarchy Viewer window, as shown in Figure 35–2. 35 CHAPTER 35: Development Tools 316 Figure 35–1. ReadWrite demo application Figure 35–2. Hierarchy Viewer main window CHAPTER 35: Development Tools 317 The list on the left shows the various emulators you have opened. The number after the hyphen should line up with the number in parentheses in your emulator’s title bar. When you click an emulator, the list of windows available for examination appears on the right, as shown in Figure 35–3. Figure 35–3. Hierarchy Viewer list of available windows Notice how there are many other windows besides our open activity, including the Launcher window (i.e., the home screen), the Keyguard window (i.e., the “Press Menu to Unlock” black screen you get when first opening the emulator), and so on. Your activity will be identified by application package and class (e.g., com.commonsware.android.files/ ). Things get interesting when you choose a window and click Load View Hierarchy. After a few seconds, the details spring into view, in a perspective called the Layout view, as shown in Figure 35–4. . com.commonsware.android.dialer; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.Button;. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent". <Button android:id="@+id/dial" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="Dial