Sie sind auf Seite 1von 9

354 CHAPTER 9: Using the Media Framework and Telephony APIs

conn = null;
}
}
}
Listing 9–9 shows an activity class that adds a file to the MediaStore. If the add is
successful, the added file is displayed to the user via an intent. What happens behind
the scenes is that the file is inspected by the MediaScanner to determine what type of file
it is and other relevant details about it. Of course, we could have given the MediaScanner
the MIME type as the second argument to scanFile(). If MediaScanner can’t determine
what the type of the file is by the extension, it won’t get added. If the file belongs in the
MediaStore, a database entry is made into the media provider database. The file itself
doesn’t move. But now the media provider knows about this file. If you added an image
file, you can now open the Gallery application and see it. If you added a music file, it will
now show up in the Music application.
If you want to see inside the media provider’s database, open a tools window, launch
adb shell then navigate on the device to
/data/data/com.android.providers.media/databases. There you will find databases,
one of which is internal.db. There could be external database files there also,
corresponding to one or more SD cards. Since you can use multiple SD cards with an
Android phone, there could also be multiple external database files there. You can use
the sqlite3 utility to inspect the tables in these databases. There are tables for audio,
images, and video. See Chapter 3 for more information on using sqlite3.
This concludes our discussion of the media APIs. We hope you’ll agree that playing
and recording media content is simple with Android. Now we’ll move on to the
telephony APIs.

Using the Telephony APIs


In this section, we are going to explore Android’s telephony APIs. Specifically, we will
show you how to send and receive SMS messages, after which we’ll explore making
and receiving phone calls. We’ll start with SMS.

Working with SMS


SMS stands for Short Message Service, as we mentioned earlier, but it’s commonly
called text messaging. The Android SDK supports sending and receiving text messages.
We’ll start by discussing various ways to send SMS messages with the SDK.

Sending SMS Messages


To send a text message from your application, you will add the <uses-permission
android:name="android.permission.SEND_SMS" /> permission to your manifest file and
then use the android.telephony.SmsManager class (see Listing 9–10).
CHAPTER 9: Using the Media Framework and Telephony APIs 355

Listing 9–10. Sending SMS (Text) Messages


<?xml version="1.0" encoding="utf-8"?>
<!-- This file is /res/layout/main.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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="Destination Address:" />

<EditText android:id="@+id/addrEditText"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:phoneNumber=”true” android:text="9045551212" />

</LinearLayout>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="wrap_content">

<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Text Message:" />

<EditText android:id="@+id/msgEditText" android:layout_width="fill_parent"


android:layout_height="wrap_content" android:text="hello sms" />

</LinearLayout>

<Button android:id="@+id/sendSmsBtn" android:layout_width="wrap_content"


android:layout_height="wrap_content" android:text="Send Text Message" />

</LinearLayout>

import android.app.Activity;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class TelephonyDemo extends Activity


{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);

Button sendBtn = (Button)findViewById(R.id.sendSmsBtn);


356 CHAPTER 9: Using the Media Framework and Telephony APIs

sendBtn.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View view) {
EditText addrTxt =
(EditText)TelephonyDemo.this.findViewById(R.id.addrEditText);

EditText msgTxt =
(EditText)TelephonyDemo.this.findViewById(R.id.msgEditText);

try {
sendSmsMessage(
addrTxt.getText().toString(),msgTxt.getText().toString());
Toast.makeText(TelephonyDemo.this, "SMS Sent",
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(TelephonyDemo.this, "Failed to send SMS",
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}});
}

@Override
protected void onDestroy() {
super.onDestroy();
}

private void sendSmsMessage(String address,String message)throws Exception


{
SmsManager smsMgr = SmsManager.getDefault();
smsMgr.sendTextMessage(address, null, message, null, null);
}
}
The example in Listing 9–10 demonstrates sending SMS text messages using the
Android SDK. Looking at the layout snippet first, you can see that the user interface has
two EditText fields: one to capture the SMS recipient’s destination address (the phone
number), and another to hold the text message. The user interface also has a button to
send the SMS message, as shown in Figure 9–7.

Figure 9–7. The UI for the SMS example


CHAPTER 9: Using the Media Framework and Telephony APIs 357

The interesting part of the sample is the sendSmsMessage() method. The method uses
the SmsManager class’s sendTextMessage() method to send the SMS message. Here’s
the signature of SmsManager.sendTextMessage():
sendTextMessage(String destinationAddress, String smscAddress, String textMsg,
PendingIntent sentIntent, PendingIntent deliveryIntent);
In this example, you populate only the destination address and the text-message
parameters. You can, however, customize the method so it doesn’t use the default SMS
center (the address of the server on the cellular network that will dispatch the SMS
message). You can also implement a customization in which pending intents are called
when the message is sent and a delivery notification has been received.
All in all, sending an SMS message is about as simple as it gets with Android. Realize
that, with the emulator, your SMS messages are not actually sent to their destinations.
You can, however, assume success if the sendTextMessage() method returns without an
exception. As shown in Listing 9–10, you use the Toast class to display a message in
the UI to indicate whether the SMS message was sent successfully.
Sending SMS messages is only half the story. Now we’ll show you how to monitor
incoming SMS messages.

Monitoring Incoming SMS Messages


The first step in monitoring incoming SMS messages is to request permission to receive
them. Using the same application that you just created to send SMS messages, add the
<uses-permission android:name="android.permission.RECEIVE_SMS" /> permission to
your manifest file. Next, you’ll need to implement a monitor to listen for SMS messages.
You accomplish this by implementing a BroadcastReceiver for the action <action
android:value="android.provider.Telephony.SMS_RECEIVED" />. To implement the
receiver, write a class that extends android.content.BroadcastReceiver and then
register the receiver in your manifest file (within the <application>). Listing 9–11
demonstrates this.
Listing 9–11. Monitoring SMS Messages
<receiver android:name="MySMSMonitor">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>

public class MySMSMonitor extends BroadcastReceiver


{
private static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";
@Override
public void onReceive(Context context, Intent intent)
{
if(intent!=null && intent.getAction()!=null &&
ACTION.compareToIgnoreCase(intent.getAction())==0)
{
Object[]pduArray= (Object[]) intent.getExtras().get("pdus");
358 CHAPTER 9: Using the Media Framework and Telephony APIs

SmsMessage[] messages = new SmsMessage[pduArray.length];


for (int i = 0; i<pduArray.length; i++) {
messages[i] = SmsMessage.createFromPdu ((byte[])pduArray [i]);
}
Log.d("MySMSMonitor","SMS Message Received.");
}
}
}
The top portion of Listing 9–11 is the manifest definition for the BroadcastReceiver to
intercept SMS messages. The SMS monitor class is MySMSMonitor. The class
implements the abstract onReceive() method, which is called by the system when an
SMS message arrives. One way to test the application is to use the Emulator Control
view in Eclipse. Run the application in the emulator and then go to Window ➤ Show
View ➤ Other ➤ Android ➤ Emulator Control. The user interface allows you to send data
to the emulator to emulate receiving an SMS message or phone call. As shown in Figure
9–8, you can send an SMS message to the emulator by populating the “Incoming
number” field and then selecting the SMS radio button. Then type some text in the
Message field and click the Send button. Doing this sends an SMS message to the
emulator and invokes your BroadcastReceiver’s onReceive() method.

Figure 9–8. Using the Emulator Control UI to send SMS messages to the emulator

The onReceive() method will have the broadcast intent, which will contain the
SmsMessage in the bundle property. You can extract the SmsMessage by calling
intent.getExtras().get("pdus"). This call returns an array of objects defined in
Protocol Description Unit (PDU) mode—an industry-standard way of representing an
SMS message. You can then convert the PDUs to Android SmsMessage objects, as
shown in Listing 9–11. As you can see, you get the PDUs as an object array from the
intent. You then construct an array of SmsMessage objects, equal to the size of the PDU
array. Finally, you iterate over the PDU array, and create SmsMessage objects from the
PDUs by calling SmsMessage.createFromPdu(). What you do after reading the incoming
message must be quick. A broadcast receiver gets high priority in the system, but must
CHAPTER 9: Using the Media Framework and Telephony APIs 359

be done quickly and does not get put into the foreground for the user to see. Therefore,
your options are limited. You should not do any direct UI work. Issuing a Notification is
fine, as is starting a service to continue work there. Once the onReceive() method
completes, the hosting process of the onReceive() method could get killed at any time.
Starting a service is okay but binding to one is not, since that would mean your process
needs to exist for a while, which might not happen.
Now let’s continue our discussion about SMS by looking at how you can work with
various SMS folders.

Working with SMS Folders


Accessing the SMS inbox is another common requirement. To get started, you need to
add read-SMS permission (<uses-permission
android:name="android.permission.READ_SMS"/>) to the manifest file. Adding this
permission gives you the ability to read from the SMS inbox.
To read SMS messages, you need to execute a query on the SMS inbox, as shown in
Listing 9–12.
Listing 9–12. Displaying the Messages from the SMS Inbox
<?xml version="1.0" encoding="utf-8"?>
<!-- This file is /res/layout/sms_inbox.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView android:id="@+id/row"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>

</LinearLayout>

import android.app.ListActivity;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.widget.ListAdapter;
import android.widget.SimpleCursorAdapter;

public class SMSInboxDemo extends ListActivity {

private ListAdapter adapter;


private static final Uri SMS_INBOX = Uri.parse("content://sms/inbox");

@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
Cursor c = getContentResolver()
.query(SMS_INBOX, null, null, null, null);
startManagingCursor(c);
360 CHAPTER 9: Using the Media Framework and Telephony APIs

String[] columns = new String[] { "body" };


int[] names = new int[] { R.id.row };
adapter = new SimpleCursorAdapter(this, R.layout.sms_inbox, c, columns,
names);

setListAdapter(adapter);
}
}
Listing 9–12 opens the SMS inbox and creates a list in which each item contains the
body portion of an SMS message. The layout portion of Listing 9–12 contains a simple
TextView that will hold the body of each message in a list item. To get the list of SMS
messages, you create a URI pointing to the SMS inbox (content://sms/inbox) and then
execute a simple query. You then filter on the body of the SMS message and set the list
adapter of the ListActivity. After executing the code from Listing 9–12, you’ll see a list
of SMS messages in the inbox. Make sure you generate a few SMS messages using the
Emulator Control before running the code on the emulator.
Because you can access the SMS inbox, you would expect to be able to access other
SMS-related folders such as the sent folder or the draft folder. The only difference
between accessing the inbox and accessing the other folders is the URI you specify. For
example, you can access the sent folder by executing a query against
content://sms/sent. Following is the complete list of SMS folders and the URI for each
folder:
 All: content://sms/all
 Inbox: content://sms/inbox
 Sent: content://sms/sent
 Draft: content://sms/draft
 Outbox: content://sms/outbox
 Failed: content://sms/failed
 Queued: content://sms/queued
 Undelivered: content://sms/undelivered
 Conversations: content://sms/conversations
Android combines MMS and SMS and allows you to access content providers for both
at the same time, using an AUTHORITY of mms-sms. Therefore, you can access a URI
such as this:
content://mms-sms/conversations

Sending E-mail
Now that you’ve seen how to send SMS messages in Android, you might assume that
you can access similar APIs to send e-mail. Unfortunately, Android does not provide
APIs for you to send e-mail. The general consensus is that users don’t want an
CHAPTER 9: Using the Media Framework and Telephony APIs 361

application to start sending e-mail on their behalf. Instead, to send e-mail, you have to
go through the registered e-mail application. For example, you could use ACTION_SEND to
launch the e-mail application:

Intent emailIntent=new Intent(Intent.ACTION_SEND);

String subject = "Hi!";


String body = "hello from android....";

String[] extra = new String[]{"aaa@bbb.com"};


emailIntent.putExtra(Intent.EXTRA_EMAIL, extra);

emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
emailIntent.putExtra(Intent.EXTRA_TEXT, body);
emailIntent.setType("message/rfc822");

startActivity(emailIntent);
This code launches the default e-mail application and allows the user to decide whether
to send the e-mail or not. Other “extras” that you can add to an email intent include
EXTRA_CC and EXTRA_BCC.
Now let’s talk about the telephony manager.

Working with the Telephony Manager


The telephony APIs also include the telephony manager
(android.telephony.TelephonyManager), which you can use to obtain information about
the telephony services on the device, get subscriber information, and register for
telephony state changes. A common telephony use case requires that an application
execute business logic upon incoming phone calls. For example, a music player might
pause itself for an incoming call, and resume when the call has been completed. So in
this section, we are going to show you how to register for telephony state changes and
how to detect incoming phone calls. Listing 9–13 shows the details.
Listing 9–13. Using the Telephony Manager
public class TelephonyServiceDemo extends Activity
{
private static final String TAG="TelephonyServiceDemo";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
TelephonyManager teleMgr =
(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
teleMgr.listen(new MyPhoneStateListener(),
PhoneStateListener.LISTEN_CALL_STATE);
}
class MyPhoneStateListener extends PhoneStateListener
{
362 CHAPTER 9: Using the Media Framework and Telephony APIs

@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch(state)
{
case TelephonyManager.CALL_STATE_IDLE:
Log.d(TAG, "call state idle...incoming number is["+
incomingNumber+"]");break;
case TelephonyManager.CALL_STATE_RINGING:
Log.d(TAG, "call state ringing...incoming number is["+
incomingNumber+"]");break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d(TAG, "call state Offhook...incoming number is["+
incomingNumber+"]");break;
default:
Log.d(TAG, "call state ["+state+"]incoming number is["+
incomingNumber+"]");break;
}
}
}
}
When working with the telephony manager, be sure to add the <uses-permission
android:name="android.permission.READ_PHONE_STATE" /> permission to your manifest
file so you can access phone-state information. As shown in Listing 9–13, you get
notified about phone-state changes by implementing a PhoneStateListener and calling
the listen() method of the TelephonyManager. When a phone call arrives, or the phone
state changes, the system will call your PhoneStateListener’s onCallStateChanged()
method with the new state and the incoming phone number. In the case of an incoming
call, you look for the CALL_STATE_RINGING state. You write a debug message to the log
file in this example, but your application could implement custom business logic in its
place. To emulate incoming phone calls, you can use Eclipse’s Emulator Control UI, as
you did with SMS messages (see Figure 9–8).
When dealing with phone-state changes, you might also need to get the subscriber’s
(user’s) phone number. TelephonyManager.getLine1Number() will return that for you.

Summary
In this chapter, we talked about the Android media framework and the telephony APIs.
With respect to media, we showed you how to play audio and video. We also showed
you how to record audio and video, both directly and via intents.
In the second part of the chapter, we talked about telephony services in Android.
Specifically, we showed you how to send text messages and how to monitor incoming
text messages. We also showed you how to access the various SMS folders on the
device. We concluded with a discussion of the TelephonyManager class.
In the next chapter, we are going to turn our attention to 3D graphics by discussing how
to use OpenGL with your Android applications.

Das könnte Ihnen auch gefallen