Android Basic Training Course: Use Telephony API

    Most Android devices are smartphones, but currently we are not yet talking about how how can develop an app uses the phone's features. In this post, we will look at ways how to send SMS messages and make a call. By this, you can learn about developing the basic features of Android phones.

Sending SMS

    In Android, there are 2 ways to send a SMS: by SmsManager and implic Intent.
    With SmsManager, the message will immediately sent and user can't customizing it any more. This process will perform with this code:
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage("[destination_phone_number]", null, "[sms_content]", null, null);
    However, through Intent, System will call the built-in SMS application in OS and through it, you can preview and edit the phone number or SMS content:
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.putExtra("address", "[destination_phone_number]");
        intent.putExtra("sms_body", "[sms_message]");
        intent.setData(Uri.parse("smsto:" + "[destination_phone_number]"));
        intent.setType("vnd.android-dir/mms-sms");
        startActivity(intent);
    Both ways nee SEND_SMS permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.SEND_SMS" />

Now, I provide an example which sending SMS through Intent. Firstly, create a simple layout like this:
activity_sms.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".SMSActivity">

    <EditText
        android:id="@+id/txt_phone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:hint="Enter Phone Number"
        android:inputType="phone"/>

    <EditText
        android:id="@+id/sms_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter SMS"/>

    <Button
        android:id="@+id/btnSendSMS"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="Send Sms" />

</LinearLayout>

    In programmatically code, we will call the default built-in SMS app to send data after click the Button:
SMSActivity.java
package info.devexchanges.telephony;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class SMSActivity extends AppCompatActivity {

    private Button btnSend;
    private EditText txtPhoneNumber;
    private EditText txtMessageContent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sms);

        btnSend = (Button) findViewById(R.id.btnSendSMS);
        txtPhoneNumber = (EditText) findViewById(R.id.txt_phone);
        txtMessageContent = (EditText) findViewById(R.id.sms_content);

        btnSend.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                sendSMSMessage();
            }
        });
    }

    protected void sendSMSMessage() {
        String phoneNo = txtPhoneNumber.getText().toString().trim();
        String message = txtMessageContent.getText().toString().trim();

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.putExtra("address", phoneNo);
        intent.putExtra("sms_body", message);
        intent.setData(Uri.parse("smsto:" + phoneNo));
        intent.setType("vnd.android-dir/mms-sms");
        startActivity(intent);
    }
}
    After running this activity, we can see this result:
    Filling content on EditTexts, click "Send SMS", you will be redirected to SMS application. You can edit the message and phone number before sending it here:

Making a phone call

    Another important feature of a phone is making a call. We can call the "dial screen" to customizing the phone to call by using Intent.ACTION_DIAL or directly call by using Intent.ACTION_CALL.
    With the first case, it's seem so simple, with Intent.ACTION_DIAL, we can go to the "dial srceen" of Android OS. Suppose we have a simple layout contains only 1 Button and 1 EditText like this:
activity_call.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="@dimen/activity_horizontal_margin">

    <EditText
        android:id="@+id/txt_phone"
        android:hint="Input a phone number here"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="phone" />

    <Button
        android:id="@+id/btn_call"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Call" />

</LinearLayout>

    Layout preview:

    Put some programmatically code to handling button event (redirect user to "dial screen" with input phone number:
DialingActivity.java
package info.devexchanges.telephony;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class DialingActivity extends AppCompatActivity {

    private Button btnCall;
    private EditText txtPhone;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_call);

        txtPhone = (EditText) findViewById(R.id.txt_phone);
        btnCall = (Button)findViewById(R.id.btn_call);

        btnCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (txtPhone.getText().toString().trim().equals("")) {
                    Toast.makeText(DialingActivity.this, "Please input a phone number", Toast.LENGTH_SHORT).show();
                } else {
                    String uri = "tel:"+ txtPhone.getText().toString();
                    Intent dialIntent = new Intent(Intent.ACTION_DIAL, Uri.parse(uri));
                    startActivity(dialIntent);
                }
            }
        });
    }
}

    Running this activity, input a phone number to the EditText:
    Click "Call", we will see the soft phone keyboard, you still can customizing the phone number here:
     When make a call directly from programmatically code, although the Intent is sufficient for the phone call, in some cases we want to monitor the phone state. In such situations, we use PhoneStateListener and TelephonyManager classes. In this example we create our own PhoneStateListener, in order to handle some states of the phone call. More specifically, in the state CALL_STATE_IDLE, we want to return to our application’s main activity after the end of the call. For that reason we create a suitable Intent, as you can see in the code below:
CallingActivity.java
package info.devexchanges.telephony;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class CallingActivity extends AppCompatActivity {

    private Button btnCall;
    private EditText txtPhone;
    private final static String TAG = CallingActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_call);

        txtPhone = (EditText) findViewById(R.id.txt_phone);
        btnCall = (Button) findViewById(R.id.btn_call);

        // add PhoneStateListener for monitoring
        CustomPhoneListener phoneListener = new CustomPhoneListener();
        TelephonyManager telephonyManager =
        (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);

        // receive notifications of telephony state changes
        telephonyManager.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);


        btnCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (txtPhone.getText().toString().trim().equals("")) {
                    Toast.makeText(CallingActivity.this, "Please input a phone number", Toast.LENGTH_SHORT).show();
                } else {
                    try {
                        String uri = "tel:" + txtPhone.getText().toString();
                        Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse(uri));
                        if (ActivityCompat.checkSelfPermission(CallingActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
                            return;
                        }
                        startActivity(callIntent);
                    } catch (Exception e) {
                        Toast.makeText(getApplicationContext(), "Your call has failed...", Toast.LENGTH_SHORT).show();
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    private class CustomPhoneListener extends PhoneStateListener {

        private boolean onCall = false;

        @Override
        public void onCallStateChanged(int state, String incomingNumber) {

            switch (state) {
                case TelephonyManager.CALL_STATE_RINGING:
                    // phone ringing...
                    Log.i(TAG, "Destination phone is ringing, please wait...");
                    break;

                case TelephonyManager.CALL_STATE_OFFHOOK:
                    // one call exists that is dialing, active, or on hold
                    Log.i(TAG, "on Calling...");

                    //because user answers the incoming call
                    onCall = true;
                    break;

                case TelephonyManager.CALL_STATE_IDLE:
                    // in initialization of the class and at the end of phone call
                    // detect flag from CALL_STATE_OFFHOOK
                    if (onCall) {
                        Log.i(TAG, "Restarting app after a call...!");

                        // restart our application
                        Intent restart = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
                        restart.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        startActivity(restart);

                        onCall = false;
                    }
                    break;
                default:
                    break;
            }
        }
    }
}

    With this approach, we need CALL_PHONE and READ_PHONE_STATE permissions in AndroidManifest.xml:
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

Conclusions

    This post is talking about using the basic features of a phone: send text messages and make calls. You can read the next post to learn about sending an email with Intent. Further, you can learn by yourself the way to listen for incoming messages by BroadcastReceiver. Finally, click the button below to view demo project on @Github.




Share


Previous post
« Prev Post
Next post
Next Post »