1

I am trying to read all incoming SMS in my Android application. I have written a Broadcast Receiver to read the messages and have added the permissions for it in the AndroidManifest. I am getting the following error:

android.content.ActivityNotFoundException: Unable to find explicit activity class {com.example.asus.otpclippr/com.example.asus.otpclippr.readerService}; have you declared this activity in your AndroidManifest.xml?

This is the AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.asus.otpclippr">
<uses-permission-sdk-23 android:name="android.permission.BROADCAST_SMS"/>
<uses-permission-sdk-23 android:name="android.permission.RECEIVE_SMS" />
<uses-permission-sdk-23 android:name="android.permission.SEND_SMS" />
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <receiver android:name="com.example.asus.otpclippr.readerService" >
        <intent-filter>
            <action android:name="android.provider.Telephony.SMS_RECEIVED"      />
        </intent-filter>
    </receiver>
</application>

This is the MainActivity.java package com.example.asus.otpclippr;

import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;

public class MainActivity extends AppCompatActivity {
    CheckBox copyClip, createNotif ;
    Button btn ;
    private BroadcastReceiver br ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    copyClip = (CheckBox)findViewById(R.id.checkBox) ;
    createNotif = (CheckBox)findViewById(R.id.checkBox2) ;
    btn = (Button)findViewById(R.id.button) ;
    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            boolean res = false ;
            res = isMyServiceRunning(readerService.class) ;
            Intent intent = new     Intent(MainActivity.this,readerService.class) ;
            //intent.setAction("android.provider.Telephony.SMS_RECEIVED") ;
            intent.putExtra("flag1",copyClip.isChecked());
            intent.putExtra("flag2",createNotif.isChecked()) ;
            Log.d("Checkpoint1","calling broadcast") ;
            startActivity(intent);
        }
    });

}

/*public boolean isMyServiceRunning(Class<?> serviceClass){
    ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE) ;
    for(ActivityManager.RunningServiceInfo service : activityManager.getRunningServices(Integer.MAX_VALUE)){
        if(serviceClass.getName().equals(service.service.getClassName())){
            return true ;
        }
    }
    return false ;
    }*/
}

And this is the BroadcastReceiver package com.example.asus.otpclippr;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.provider.Telephony;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;

/**
 * Created by ASUS on 27-12-2016.
 */

public class readerService extends BroadcastReceiver {
    SmsManager smsManager = SmsManager.getDefault() ;
    String[] msg ;
    @Override
    public void onReceive(Context context, Intent intent) {



    final Bundle bundle = intent.getExtras() ;
    try{
        if(bundle!=null) {
            SmsMessage smsMessage;

            if (Build.VERSION.SDK_INT >= 19) { //KITKAT
                SmsMessage[] msgs = Telephony.Sms.Intents.getMessagesFromIntent(intent);
                smsMessage = msgs[0];
            } else {
                Object pdus[] = (Object[]) bundle.get("pdus");
                smsMessage = SmsMessage.createFromPdu((byte[]) pdus[0]);
            }
            String message = smsMessage.getMessageBody() ;
            String[] checks = new String[]{"OTP","Transaction","Password","key","card","txn"} ;
            msg = message.split(" ") ;
            Log.d("Message",message) ;
            for(int i=0;i<checks.length;i++){
                if(message.contains(checks[i])){
                    checkforOTP(context,message) ;
                    Log.d("Check2","Checking for OTP") ;
                    break;
                }
            }

            /*final Object[] pdusObj = (Object[]) bundle.get("pdus");
            for (int i = 0; i < pdusObj.length; i++) {

                SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
                String phoneNumber = currentMessage.getDisplayOriginatingAddress();

                String senderNum = phoneNumber;
                String message = currentMessage.getDisplayMessageBody();

                Log.d("SmsReceiver", "senderNum: " + senderNum + "; message: " + message);
                String[] msg = message.split(" ") ;
                Toast.makeText(context,message,Toast.LENGTH_SHORT).show();
                String[] checks = new String[]   {"OTP","Transaction","Password","key","card"} ;
                for(int j=0; j< checks.length; j++){
                    if(message.contains(checks[j])){
                        checkforOTP(message) ;
                        break;
                    }
                }
            }*/
        }
    }catch (Exception e){
        e.printStackTrace();
    }
}

public void checkforOTP(Context context ,String message){
    int pos = message.indexOf("is") ;
    String msg1 = message.substring(pos,message.length()) ;
    String otp1 = msg1.split(" ")[0];
    String msg2 = message.substring(0,pos) ;
    String[] tempA = msg2.split(" ") ;
    String otp2 = tempA[tempA.length -1] ;
    if(isValid(otp1)){
        Toast.makeText(context,"OTP is"+otp1,Toast.LENGTH_SHORT).show();
    }
    else if(isValid(otp2)){
        Toast.makeText(context,"OTP is "+otp2,Toast.LENGTH_SHORT).show();
    }
    else{
        Log.d("check3","Wrong call") ;
    }

}

public boolean isValid(String x){
    if(!(x.length()==4 || x.length() ==6)){
        return false ;
    }
    if(x.matches("\\d+")){
        return  true ;
    }
    return  false ;
}
}

What is the correct way to call a Broadcast Receiver from the MainActivity?Thanks in advance

user6739649
  • 35
  • 1
  • 1
  • 5

1 Answers1

0

You are doing this in an OnClickListener:

       Intent intent = new     Intent(MainActivity.this,readerService.class) ;
        //intent.setAction("android.provider.Telephony.SMS_RECEIVED") ;
        intent.putExtra("flag1",copyClip.isChecked());
        intent.putExtra("flag2",createNotif.isChecked()) ;
        Log.d("Checkpoint1","calling broadcast") ;
        startActivity(intent);

You are calling startActivity() with an Intent that targets a BroadcastReceiver. readerService is a BroadcastReceiver, not an Activity. This can't work.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • Thanks. Can you suggest some changes which can be made so that onClickListener triggers the Broadcast Receiver?Thanks in advance. – user6739649 Jan 05 '17 at 13:38
  • Sorry, I don't understand. Your `BroadcastReceiver` will get triggered when an incoming SMS arrives. Isn't that what you want? – David Wasser Jan 05 '17 at 14:56
  • Yes. I am trying to read the incoming SMS and create a Toast message with it. Nothing needs to be changed?I thought there should be some sort of a call to the broadcast receiver. – user6739649 Jan 05 '17 at 17:07
  • No, Your `BroadcastReceiver` is configured in your manifest. It will be called when an SMS arrives even if your app is not running. You just need to make sure that you run your app at least once after installation. The app (`Activity`) doesn't actually need to do anything. – David Wasser Jan 05 '17 at 17:11
  • Oh.. I didn't know that. But still it is not working as required. I have added the permissions as well. Should I change anything in the code?Thanks in advance. – user6739649 Jan 05 '17 at 17:42
  • Does your `onReceive()` method get called? What happens? – David Wasser Jan 05 '17 at 18:06
  • onReceive() is not called during an Incoming SMS. – user6739649 Jan 06 '17 at 13:57
  • What device are you testing on? Running what version of Android? – David Wasser Jan 06 '17 at 13:58
  • Android Device. Moto X play. Android version 6.0.1 – user6739649 Jan 06 '17 at 14:26
  • Starting with Android 6, users can grant and revoke permissions. Check if you have granted the "RECEIVE_SMS" permission in the security settings on the phone – David Wasser Jan 06 '17 at 14:38
  • Also, you should check that the permission has been granted at runtime. Look at https://developer.android.com/training/permissions/requesting.html and add this permission check code in your `Activity` to verify that your app has the RECEIVE_SMS permission. – David Wasser Jan 06 '17 at 14:44
  • I granted the permission now and it works fine. Thanks a lot. – user6739649 Jan 06 '17 at 14:52
  • Brilliant! Glad I could be of assistance. – David Wasser Jan 06 '17 at 15:14