How to Make Calls and Use SMS in Android Apps

In this tutorial, you'll learn about the Android Telephony and SMS API. You'll learn how to make a call from your app and how to monitor phone call events, as well as how to send and receive SMS.

1. How to Make A Call 

To start off, I'll show you how to initiate a call from your application either by using the phone dialer app or directly from your app to make it easier for your users.

Create a New Android Studio Project

Fire up Android Studio and create a new project with an empty activity called MainActivity.

Android Studio create  a new Activity screenshot

Lay Out the Screen

For now, our layout will just have an EditText field and a Dial button:

Emulator dial screen with phone number given

Modify the MainActivity Class

In the code block below, we are creating an ACTION_DIAL intent to display the phone dialer. The phone number is parsed from our tel URI scheme: tel:XXXXXXXX. Note that you don't need any permission for this to work:

If you run the app and click the dial button, you'll be taken to the dialer app, and from there you have to actually dial the number. You can change this flow to actually make the call from within your app by simply changing the ACTION_DIAL intent to ACTION_CALL instead. This will require the android.permission.CALL_PHONE permission, though. 

Emulator screen defualt phone dialer with the phone number

2. Monitoring Phone Call Events

In this section, we are going to learn how to monitor phone call events in the Android system. The phone can be in three states: 

  1. idle (when it is unused)
  2. ringing (when there is an incoming call)
  3. off-hook (when the call is answered)

Add the Permission 

We need the permission READ_PHONE_STATE to be able to monitor the phone state. Add it to AndroidManifest.xml:

Create the PhoneStateListener Object

We create an object of the PhoneStateListener class, and then override its onCallStateChanged() method (in IntelliJ it is easy to do this with Control-O, and then select or search for the method to override). We'll handle changes to the call state changes by displaying a Toast. Note that we can also access the incoming phone numbers when this method is triggered:

Depending on your application needs, you could also override one of these other event methods: onCellInfoChanged()onCallForwardingIndicatorChanged()onCellLocationChanged(), or onSignalStrengthChanged().

Listening to the Phone Call State

In order to begin listening to the phone call state, we need to get the TelephonyManager from the system service and initialize it in onCreate().

In the onResume() method, we can begin to listen using the TelephonyManager listen() method, passing it the PhoneStateListener instance and the static LISTEN_CALL_STATE. We stop listening in the onStop() method by passing the LISTEN_NONE as the second argument to listen().

Other phone listening options possible are LISTEN_CELL_LOCATIONLISTEN_SIGNAL_STRENGTHLISTEN_CALL_FORWARDING_INDICATOR, and LISTEN_CELL_INFO.

Finally, run the app and make sure an incoming call comes in. 

Emulator incoming call states

This monitoring will only work when the app is in the foreground. For this to work in the background (when our application is not running), we would need to create a BroadcastReceiver so that even if the app isn't running, we can still monitor for phone call states. Depending on your app requirements, that could be a much better way to listen for phone call state changes. I'll show you how to do this in the next section.

Be aware that we are only monitoring incoming calls. For us to monitor outgoing calls, we need additional permissions. To monitor outgoing calls, include the following line in your AndroidManifest.xml file.

How to Use the Emulator to Make Calls and Send SMS Messages

You can use your emulator to simulate making a call or sending an SMS message, but you'll need to do a little setup. Open your emulator, click the last button on the right-side navigation bar to open the extended control dialog, and then select the phone control button. 

Using emulator to make call and send SMS

3. Monitoring Phone Call Events in the Background

Create a BroadcastReceiver

Just like in the previous section, we need to create an event listener to monitor phone state changes. The major difference is that this time we'll extend the BroadcastReceiver base class so we can listen for the phone call state even if the application is not running. Be sure not to register the listener more than once! Our check for this is on line 36.

Modify AndroidManifest.xml

A broadcast receiver works only if it is registered. We need to tell the Android system about our broadcast receiver by registering it in the AndroidManifest.xml file by connecting our PhoneCallStateReceiver class to the <intent-filter> that describes the system broadcast we wish to receive—in this case, PHONE_STATE.

Monitoring Outgoing Calls

For outgoing calls, you need to include the NEW_OUTGOING_CALL action intent <action android:name="android.intent.action.NEW_OUTGOING_CALL"/> in the <intent-filter> of the receiver in AndroidManifest.xml

To get the phone number of the intended outgoing call, inside the onReceive(Context, Intent) method, we get the number from the intent as an extra. To prevent that intended call from going through, we can call setResultData() and pass it a null argument. The resultData is used as the actual number to call. 

You can learn more about broadcasts and broadcast receivers in our tutorial here on Envato Tuts+:

4. Sending SMS Messages

You have just two major choices for sending SMS: using the device SMS client application or skipping the client by sending the SMS directly from your app. We'll look at both scenarios, and you can decide which one is better for your use case. Let's start by sending an SMS using the device SMS client.

Set Up the Layout

First, we need to modify our main layout to have an EditText field for the message and a Send Message button.

Modify the MainActivity 

Inside our onCreate() method in our MainActivity class, create an intent with ACTION_SENDTO as the first argument and a smsto:<phone number> URI as the second argument. The text message will be the value of the sms_body extra: 

Here, the SMS client will monitor the status of the message delivery. 

Run the App

When all required fields are entered, clicking the Send SMS button will open the user's SMS client, or will give the user options to select an app if one hasn't already been chosen.

Send SMS flow

5. Sending SMS Messages Directly

Next let's see how to send the SMS directly from our application instead of using the device SMS client. 

Add Permission in AndroidManifest.xml

As usual, we need to register the permission in AndroidManifest.xml.

Modify the MainActivity class 

Next, for Android 6.0 (API level 23) and above, we need to request the SEND_SMS permission during runtime. 

To learn more about Android runtime permissions and how they've changed in version 6.0, check out our tutorial here on Envato Tuts+:

To send an SMS, we get the default SmsManager instance and then call its sendTextMessage() method, passing in the phone number as the first argument and the message as the second argument:

To monitor the status of delivery, the SMSManager sendTextMessage() method has two optional PendingIntent parameters: sentIntent and deliveryIntent.

If you want to use sentIntent, watch for the result code Activity.RESULT_OK on success, or one of RESULT_ERROR_GENERIC_FAILURERESULT_ERROR_RADIO_OFF, and RESULT_ERROR_NULL_PDU to indicate an error.

6. Receiving an SMS Message

For your app to begin receiving SMS messages from the user's phone, its best to have a broadcast receiver registered so that it can be alerted when a new SMS arrives even if your app is not running in the foreground. 

Add the Permission 

Add the RECEIVE_SMS permission to AndroidManifest.xml:

Next, we need to check and see if the app has permission to receive SMS messages at runtime. So in the MainActivity class, check for the RECEIVE_SMS permission. If it is not found, request it.

Create a Broadcast Receiver

We are retrieving each object of the SmsMessage class by using the method createFromPdu(byte[] pdu), passing it a PDU (protocol data unit). We are then adding it to our messages array. 

To support API 23 and above, you should include the format String extra (either "3gpp" for GSM/UMTS/LTE messages in 3GPP format or "3gpp2" for CDMA/LTE messages in 3GPP2 format). 

Now, run the app, close it, and send your emulated phone an SMS.

Emulator showing a toast when it receives an SMS in the background

Conclusion

In this tutorial, you learned about:

  • making a call from your app
  • monitoring phone call events
  • sending SMS messages using either the device messaging app or directly from your own app
  • receiving SMS messages in the background

There's lots more you can do with phone calls and SMS messages in Android. Visit the Android Telephony API and the SMSManager API documentation to learn more. 

In the meantime, check out some of our other posts on Android development!

Tags:

Comments

Related Articles