Hello, Developers!! In this tutorial, I will show you how to Receive SMS in Android Application and displaying only those messages which contain the keyword you enter.

Output:

Download Source code: [media-downloader media_id=”1301″ texts=”InAppMessaging.zip”]

Download APK: [media-downloader media_id=”1302″ texts=”InAppMessaging”]

Wants to Learn Advanced Android Application development from scratch- Beyond Basics

Creating New Project

Open your Android Studio & create a new Project, have taken Empty Activity for this project. We kept all the things by default and clicked finish.

Manifest declarations

To read the messages we need to add following permission in the AndroidManifest.xml

<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />

To receive SMS in the application we need to use the broadcast receiver.

The intents that are broadcast by the system or by other applications are received by Broadcast receivers.
There are two ways to make a broadcast receiver known to the system:

1. declare it in the manifest file with this element.

2. create the receiver dynamically in code and register it with the Context.registerReceiver() method.

we’ll go by method one which is by declaring it in the manifest file,

<application>
           .
           .
       <receiver android:name=".SmsBroadcastReceiver" android:exported="true" >
            <intent-filter android:priority="999" >
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
       </receiver>
</application>

Creating Layout

activity_main.xml

<?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" android:id="@+id/MainLayout">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="SMS Inbox"
        android:id="@+id/textView"
        android:layout_gravity="center_horizontal" />
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center">
        <EditText
            android:id="@+id/keyword"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="Enter Keyword"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"/>
        <ImageButton
            android:id="@+id/key_search"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:src="@android:drawable/ic_search_category_default"
            android:layout_alignParentRight="true" />
    </RelativeLayout>
    <ListView android:id="@+id/SMSList"
        android:layout_height="397dp"
        android:layout_width="match_parent"
        android:layout_margin="5dp" />

</LinearLayout>

MainActivity.java

package com.mytrendin.inappmessaging;

import android.Manifest;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends Activity implements OnItemClickListener {

    private static MainActivity inst;
    ArrayList<String> smsMessagesList = new ArrayList<String>();
    ListView smsListView;
    ArrayAdapter arrayAdapter;
    EditText keyword;
    ImageButton search;
    Boolean permission=false;
    public static final int MY_PERMISSIONS_REQUEST_RECEIVE_SMS = 99;
    public static MainActivity instance() {
        return inst;
    }

    @Override
    public void onStart() {
        super.onStart();
        inst = this;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        smsListView = (ListView) findViewById(R.id.SMSList);
        arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, smsMessagesList);
        smsListView.setAdapter(arrayAdapter);
        smsListView.setOnItemClickListener(this);
        keyword = (EditText)findViewById(R.id.keyword);
        search = (ImageButton)findViewById(R.id.key_search);

        refreshSmsInbox("");
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                refreshSmsInbox(keyword.getText().toString());
            }
        });
    }

    public void refreshSmsInbox(String key) {
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            permission = checkSmsPermission();
        if (permission) {
            ContentResolver contentResolver = getContentResolver();
            Cursor smsInboxCursor = contentResolver.query(Uri.parse("content://sms/inbox"), null, null, null, null);
            int indexBody = smsInboxCursor.getColumnIndex("body");
            int indexAddress = smsInboxCursor.getColumnIndex("address");
            if (indexBody < 0 || !smsInboxCursor.moveToFirst()) return;
            arrayAdapter.clear();
            do {
                String number = smsInboxCursor.getString(indexAddress);
                String message = smsInboxCursor.getString(indexBody);

                if (message.toLowerCase().contains(key.toLowerCase())) {
                    String str = "SMS From: " + number +
                            "\n" + message + "\n";
                    arrayAdapter.add(str);
                }
            } while (smsInboxCursor.moveToNext());
        }
    }

    public void updateList(final String smsMessage) {
        arrayAdapter.insert(smsMessage, 0);
        arrayAdapter.notifyDataSetChanged();
    }

    public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
        try {
            String[] smsMessages = smsMessagesList.get(pos).split("\n");
            String address = smsMessages[0];
            String smsMessage = "";
            for (int i = 1; i < smsMessages.length; ++i) {
                smsMessage += smsMessages[i];
            }
            String smsMessageStr = address + "\n";
            smsMessageStr += smsMessage;
            Toast.makeText(this, smsMessageStr, Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public boolean checkSmsPermission() {

        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.RECEIVE_SMS)
                != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.RECEIVE_SMS)) {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.RECEIVE_SMS},
                        MY_PERMISSIONS_REQUEST_RECEIVE_SMS);
            } else {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.RECEIVE_SMS},
                        MY_PERMISSIONS_REQUEST_RECEIVE_SMS);
            }
            return false;
        } else {
            return true;
        }

    }
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                     String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_RECEIVE_SMS: {
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    if (ContextCompat.checkSelfPermission(this,
                            Manifest.permission.RECEIVE_SMS)
                            == PackageManager.PERMISSION_GRANTED) {
                        refreshSmsInbox("");
                    }
                } else {
                    Toast.makeText(getApplicationContext(), "permission denied",
                            Toast.LENGTH_LONG).show();
                }
                return;
            }
        }
    }
}

Before fetching the SMS from inbox we will apply a Version check. If the Android Version is equal or above the Marshmallow version then permission has to be granted first, by the user.

if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
     permission = checkSmsPermission();

In order to read inbox, we need to make use of ContentResolver method.

ContentResolver contentResolver = getContentResolver();
Cursor smsInboxCursor = contentResolver.query(Uri.parse("content://sms/inbox"), 
                                                      null, null, null, null);

when a call to getContentResolver().query(Uri, String, String, String, String) is made. The call invokes the Content Resolver’s query method then the Content Resolver parses the URI argument and extracts its authority.
The Content Resolver will then call the Content Provider’s query method which will direct the request to the content provider which is registered with the (unique) authority after doing this the query is performed and a Cursor is returned (or an exception is thrown). The resulting behavior depends entirely on the Content Provider’s implementation.

Related:

Implement Search functionality in Android Spinner

Java static keyword – static variable, static methods, static blocks !

Read sms from Inbox and display in RecyclerView

Connecting To Phone Book, Phone Call, And Default SMS Service using Android

Send SMS using Intent

Using this cursor we get the phone number and the body of the message.

int indexBody = smsInboxCursor.getColumnIndex("body");
int indexAddress = smsInboxCursor.getColumnIndex("address");

As only those messages should be displayed which contain the keyword entered by the user the body of the message is checked for the presence of the keyword using the contains() method.

if (message.toLowerCase().contains(key.toLowerCase())) {
     String str = "SMS From: " + number + "\n" + message + "\n";
     arrayAdapter.add(str);
}

Here both message and key are converted to lower case so that the key is searched regardless of its case.

updateList() method will insert the SMS that we received to the arrayAdapter.

public void updateList(final String smsMessage) {
    arrayAdapter.insert(smsMessage, 0);
    arrayAdapter.notifyDataSetChanged();
}

SmsBroadcastReceiver.java

package com.mytrendin.inappmessaging;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;

public class SmsBroadcastReceiver extends BroadcastReceiver {

    public static final String SMS_BUNDLE = "pdus";

    SmsMessage smsMessage;
    public void onReceive(Context context, Intent intent) {
        Bundle intentExtras = intent.getExtras();
        String format = intentExtras.getString("format");
        if (intentExtras != null) {
            Object[] sms = (Object[]) intentExtras.get(SMS_BUNDLE);
            String smsMessageStr = "";
            for (int i = 0; i < sms.length; ++i) {

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    smsMessage = SmsMessage.createFromPdu((byte[]) sms[i], format);
                }
                else {
                     smsMessage = SmsMessage.createFromPdu((byte[]) sms[i]);
                }
                String smsBody = smsMessage.getMessageBody().toString();
                String address = smsMessage.getOriginatingAddress();

                smsMessageStr += "SMS From: " + address + "\n";
                smsMessageStr += smsBody + "\n";
            }
            Toast.makeText(context, smsMessageStr, Toast.LENGTH_SHORT).show();

            MainActivity inst = MainActivity.instance();
            inst.updateList(smsMessageStr);
        }
    }
}

createFromPdu() method creates a Sms Message from a raw PDU with the specified message format. The message format is passed in the SMS_RECEIVED_ACTION as the format String extra and will be either “3gpp” for GSM/UMTS/LTE messages in 3GPP format or “3gpp2” for CDMA/LTE messages in 3GPP2 format.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
       smsMessage = SmsMessage.createFromPdu((byte[]) sms[i], format);
}
else {
      smsMessage = SmsMessage.createFromPdu((byte[]) sms[i]);
}

here version check is done by calling this method as the method createFromPdu(byte[]) was deprecated in API 23 and after that createFromPdu(byte[], String) is used.

This will update the UI with a message and the SMS that we received is passed to the updateList method of MainActivity. If You are Beginner Learn Android application development from the scratch

MainActivity inst = MainActivity.instance();
inst.updateList(smsMessageStr);

If you really liked the article, please subscribe to our YouTube Channel for videos related to this article.Please find us on Twitter and Facebook.

Related Posts