Joseph
Joseph

Reputation: 1080

Broadcast receiver inside service did not listen after app removed from background

I have a broadcast receiver registered to receive SMS inside a service. The intention of the Application is to get the SMS on receive and save the contents of SMS from expected sender in Sqlite storage. The App need to capture the SMS received also even when the App is not running in background.

public class SMSService extends Service {

    private final BroadcastReceiver receiver = new BroadcastReceiver() {
        public static final String SMS_BUNDLE = "pdus";
        ContentValues userValues;
        Object[] sms;

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals("android.provider.Telephony.SMS_RECEIVED")) {
                Log.d("~~~ SMS !!!", "~~~ SMS ~~~ SMS ~~~ SMS~~~ SMS ~~~");
                AsyncSmsHandler asyncSmsHandler = new AsyncSmsHandler(context, intent);
                asyncSmsHandler.execute("");
            }
        }


        class AsyncSmsHandler extends AsyncTask<String, Void, String> {

            Context context;
            Intent intent;

            public AsyncSmsHandler(Context context, Intent intent) {
                this.context = context;
                this.intent = intent;
            }

            @Override
            protected String doInBackground(String... params) {

                String smsBody = "", address = "";
                Bundle intentExtras = intent.getExtras();
                SmsMessage smsMessage = null;
                if (intentExtras != null) {
                    sms = (Object[]) intentExtras.get(SMS_BUNDLE);

                    String smsMessageStr = "";
                    for (int i = 0; i < sms.length; ++i) {
                        smsMessage = SmsMessage.createFromPdu((byte[]) sms[i]);
                        smsBody = smsBody + smsMessage.getMessageBody();

                   smsMessageStr += smsBody + "\n";
                    }


                    address = smsMessage.getOriginatingAddress();

                    Log.d("SMS RECEIVER NUMBER", " " + smsBody + " -- " + sms.length);

                    //SAVE THE MESSAGE AND NUMBER

                }
                return "";
            }

            @Override
            protected void onPostExecute(String result) {


                // Create an explicit intent for an Activity in your app
                Intent intent = new Intent(context, AquaOrderList.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

                NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "CHANNEL_ID")
                        .setSmallIcon(R.drawable.logo)
                        .setContentTitle(“TITLE”)
                        .setContentText(“Message”)
                        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                        .setContentIntent(pendingIntent)
                        .setAutoCancel(true);

                NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);

                // notificationId is a unique int for each notification that you must define
                notificationManager.notify(1, builder.build());
            }

        }
    };

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }


    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.provider.Telephony.SMS_RECEIVED");

        registerReceiver(receiver, filter);
    }

    @Override
    public void onDestroy() {
        unregisterReceiver(receiver);
    }
}

In this way registering the receiver in onCreate and unregisterReceiver on onDestroy methods.

This work as expected but when I kill the App and after a while, If I receive SMS, it is not getting triggered. If I open the App again, after that SMS starts saving in the storage.

Is the service getting destroyed ? I checked in the "Running Services" in mobile and I can see the service running.

I have also added the permissions in manifest file.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xyz.app”>

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <service
            android:name=".SMSService"
            android:enabled="true"
            android:exported="true"></service>

        <activity
            android:name=".OrderList"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:label="@string/title_activity_order_list"
            android:theme="@style/FullscreenTheme"></activity>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

I want to have the Application listening for incoming SMS even the App is not in the stack. What can be the approach I can follow to get this done.

Upvotes: 1

Views: 1006

Answers (1)

BLH
BLH

Reputation: 153

I am not in total agreement with @Ranjan's comments. Yes, services are destroyed and kept running by android & yeah, it is difficult to run a service permanently. However if you have done everything correctly, how many ever times your service is destroyed, it would be launched again (automatically), and on launch, your receiver should be registered.


My tips are:

  • Firstly, make sure your are NOT targeting latest SDK. I am using targetSDK 10, minSDK 17, and compileSDK 26. That could make a difference on how your services are treated. Play around with these values to check if this alone makes it work.

  • Next, please follow this thread HERE and try to create your receiver properly.

  • I'm not sure about what your problem is exactly, however I can tell you, that we have a video conferencing application, that listens to incoming calls and messages. So of course, the BroadcastReceiver needs to be registered and Service should be running in the background. This app is a little old, and was developed with targetSDK 10 etc. So they are doing it in the way that was common then. We still haven't ported our application, so we don't know what problems exist in newer Android. As I mentioned, our app compiles with SDK26.


Code Sample:

public SampleService() {
    super();
    Log.d(TAG, "SampleService: Constructor");
    final HandlerThread mHandlerThread = new HandlerThread(BR_THREAD_NAME, Process.THREAD_PRIORITY_BACKGROUND);
    mHandlerThread.start();
    bgLooper = mHandlerThread.getLooper();
    mBRHandler = new Handler(bgLooper);
}

@Override
public void onCreate() {
    super.onCreate();
    Log.d(TAG, "onCreate: ");
    registerReceiver();
}

private void registerReceiver() {
    final IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(SOME_ACTION);
    myReceiver = new MyReceiver();
    registerReceiver(myReceiver, intentFilter, null, mBRHandler);
}

This should be good enough

Upvotes: 1

Related Questions