Search code examples
androidandroid-activitysmsbroadcastreceiverandroid-context

Call activity method from broadcast receiver android?


In my application I am sending a port SMS to the mobile. And when the message is recieved I need to perform some task in my activity and update the UI.

Manifest Declaration of receiver

 <receiver android:name="com.vfi.BinarySMSReceiver" >
        <intent-filter android:priority="10" >
            <action android:name="android.intent.action.DATA_SMS_RECEIVED" />

            <data
                android:host="*"
                android:port="9512"
                android:scheme="sms" />
        </intent-filter>
    </receiver>

Receiver class

public class BinarySMSReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    Bundle bundle = intent.getExtras();
    SmsMessage[] msgs = null;

    if (null != bundle) {
        String info = "SMS from ";
        String sender = "";
        String msg = "";

        Object[] pdus = (Object[]) bundle.get("pdus");

        msgs = new SmsMessage[pdus.length];
        byte[] data = null;

        for (int i = 0; i < msgs.length; i++) {
            msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
            sender += msgs[i].getOriginatingAddress();
            info += msgs[i].getOriginatingAddress() + "\n";

            data = msgs[i].getUserData();

            for (int index = 0; index < data.length; ++index) {
                info += Character.toString((char) data[index]);
                msg += Character.toString((char) data[index]);
            }
        }
        Log.e("SakjsdMS", "akjsdhkas" + msg);
        Log.e("sender", "asdasdasdasdasdasd" + info);

        ((VerifyActivity)context).msgReceived(msg);
    }
}
}

Method in activity

public  void msgReceived(String msgContent)
{
    if(msgContent.equalsIgnoreCase(etMobile.getText().toString().trim())){
        showToast("Number Verified");
    }else{
        showToast("Sorry wrong number. Input your number again.");
    }

}

The exception I get

java.lang.RuntimeException: Unable to start receiver com.vfi.BinarySMSReceiver: java.lang.ClassCastException: android.app.ReceiverRestrictedContext cannot be cast to com.vfi.VerifyActivity
        at android.app.ActivityThread.handleReceiver(ActivityThread.java:2467)
        at android.app.ActivityThread.access$1700(ActivityThread.java:145)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1319)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5127)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641)
        at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.lang.ClassCastException: android.app.ReceiverRestrictedContext cannot be cast to com.vfi.VerifyActivity
        at com.vfi.BinarySMSReceiver.onReceive(BinarySMSReceiver.java:46)
        at android.app.ActivityThread.handleReceiver(ActivityThread.java:2460)

            at android.app.ActivityThread.access$1700(ActivityThread.java:145)

How can I get activity context in reciever to call my method??


Solution

  • I was able to solve it by declaring receiver programmatically:

    In the activity befor sending the message

    private void sendSMS() {
        BinarySMSReceiver smsReceiver = null;
        smsReceiver = new BinarySMSReceiver();
        smsReceiver.setActivityHandler(this);
        IntentFilter portIntentFilter = new IntentFilter("android.intent.action.DATA_SMS_RECEIVED");
        portIntentFilter.addDataAuthority("*", "9512");
        portIntentFilter.addDataScheme("sms");
        registerReceiver(smsReceiver, portIntentFilter);
    
    
    
            String messageText = etMobile.getText().toString().trim();
            short SMS_PORT = 9512;
            SmsManager smsManager = SmsManager.getDefault();
            smsManager.sendDataMessage(etMobile.getText().toString().trim(), null, SMS_PORT, messageText.getBytes(), null, null);
    }
    

    In receiver class

     public class BinarySMSReceiver extends BroadcastReceiver {
        VerifyActivity vAct = null;
    
        void setActivityHandler(VerifyActivity main) {
            vAct = main;
        }
    
        @Override
        public void onReceive(Context context, Intent intent) {
            Bundle bundle = intent.getExtras();
            SmsMessage[] msgs = null;
    
            if (null != bundle) {
                String info = "SMS from ";
                String sender = "";
                String msg = "";
    
                Object[] pdus = (Object[]) bundle.get("pdus");
    
                msgs = new SmsMessage[pdus.length];
                byte[] data = null;
    
                for (int i = 0; i < msgs.length; i++) {
                    msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                    sender += msgs[i].getOriginatingAddress();
                    info += msgs[i].getOriginatingAddress() + "\n";
    
                    data = msgs[i].getUserData();
    
                    for (int index = 0; index < data.length; ++index) {
                        info += Character.toString((char) data[index]);
                        msg += Character.toString((char) data[index]);
                    }
                }
    
                Log.e("message", "receiver " + msg);
                Log.e("sender", "from " + info);
                vAct.msgReceived(msg);  //activity method
            }
        }
    }
    

    Unregister the receiver

     @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(smsReceiver);
    }