Search code examples
androidbroadcastreceiverandroid-room

How to use Room Database inside BroadcastReceiver?


Good day. My app needs to receive SMS and what I am trying to do right now is I want to insert the data to the database from BroadcastReceiver as soon as the app received the message but I failed. Here is my code.

public class SmsReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        ViewModel model = ViewModelProviders.of((FragmentActivity) context).get(ViewModel.class);

        Bundle bundle = intent.getExtras();

        Object[] objects = (Object[]) Objects.requireNonNull(bundle).get("pdus");
        SmsMessage[] smsMessages = new SmsMessage[Objects.requireNonNull(objects).length];

        Sms sms = new Sms();
        for (int i = 0; i < smsMessages.length; i++) {
            smsMessages[i] = SmsMessage.createFromPdu((byte[]) objects[i]);
            sms = new Sms(
                    smsMessages[i].getOriginatingAddress(),
                    smsMessages[i].getMessageBody(),
                    smsMessages[i].getTimestampMillis()
            );
        }

        model.insert(new ReplyToVotersQueue(sms.getBody(),sms.getAddress()));
    }
}

As we can see, I am trying to insert the data to database but I've got an error that says

java.lang.RuntimeException: Unable to start receiver mgb.com.smspoll.Services.SmsReceiver: java.lang.ClassCastException: android.app.ReceiverRestrictedContext cannot be cast to androidx.fragment.app.FragmentActivity

I found from the internet while searching the answer to this problem that BroadcastReceiver cannot convert to Activity because BroadcastReceiver can run without context. If that so then is there any way to insert the data to database using room database after receiving the SMS? Since my app is an SMS Poll, I need to run my app in the background process.


Solution

  • The problem here is that you're trying to retrieve the ViewModel outside an activity or a fragment, which is not a good practice and also doesn't work.

    The solution is this:

    Separate your Room DB operation from ViewModel in a separate singleton class. Use it in ViewModel and any other place required. When Broadcast is received, write data to DB through this singleton class rather than ViewModel.

    For more, please take a look at this post: The correct way to obtain a ViewModel instance outside of an Activity or a Fragment