Search code examples
javaandroidserviceconcurrencybroadcastreceiver

multiple calls to same service leading data loss


I have a service A, which inserts MULTIPLE_RECORDS into MULTIPLE_TABLES , that MULTIPLE_TABLES i am using later in another service B. I have a PHONE_STATE receiver, which on EXTRA_STATE_IDLE calls service A. EveryThing is working superb. Now begining of the problem :


Android 5.0 behaviour : EXTRA_STATE_IDLE is triggering twice, EXTRA_STATE_RINGING is triggering twice WITH NO WAITING CALL NUMBER, EXTRA_STATE_OFFHOOK are getting triggered TWICE-TWICE.


And the problem starts, As i am starting service A from EXTRA_STATE_IDLE, How i make service A capable of DO NOT ALLOW OTHER INSTANCE TO RUN ME, IF I AM NOT FINISHED.. You can see i have tried it with Boolean variable StateIdle


Receiver :

if (action.equalsIgnoreCase("android.intent.action.NEW_OUTGOING_CALL"))
        {
            StateIdle = true;
            IsNewOutGoingCall = true;
            OutGoingPhoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
            Log.d("RECEIVER X: ", "NEW OUTGOING CALL : " + OutGoingPhoneNumber);
        }
        if (action.equalsIgnoreCase("android.intent.action.PHONE_STATE"))
        {
            if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING))
            {
                StateIdle = true;
                PhoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
                if(InComingNumbersList.contains(PhoneNumber))
                {
                    Log.d("RECEIVER X: ", "INCOMING NUMBER IS PRESENT IN LIST...");
                }
                else
                {
                    InComingNumbersList.add(PhoneNumber);
                    Log.d("RECEIVER X: ", "Incoming number : " + PhoneNumber);
                    Intent InsertDb = new Intent(context, CatchNumbers.class);
                    InsertDb.putExtra("TYPE", "INCOMING");
                    InsertDb.putExtra("PHONENUMBER", PhoneNumber);
                    startService(InsertDb);
                }
            }
            if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE))
            {
                //OutGoingPhoneNumber = "UNKNOWN";
                InComingNumbersList.clear();
                if(StateIdle)
                {
                    StateIdle = false;
                    Log.d("RECEIVER X: ", "CALL ENDED... ");
                    Intent SendSMS = new Intent(context, SendSMS.class);
                    startService(SendSMS);
                }
            }
            if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
            {
                if(IsNewOutGoingCall)
                {
                    IsNewOutGoingCall = false;
                    Log.d("RECEIVER X: ", "ACTIVE OUTGOING CALL : ");
                    Intent InsertDb = new Intent(context, CatchNumbers.class);
                    InsertDb.putExtra("TYPE", "OUTGOING");
                    InsertDb.putExtra("PHONENUMBER", OutGoingPhoneNumber);
                    startService(InsertDb);
                }

            }
        }

Thank you in advance, Hope someone helps me... :)


Solution

  • Well.., In short and sweet, If a service gets called multiple times, it starts onstartcommand multiple times... May be concurrent... Causes data loss in tables and cases in our code that is dependent on table values causes malfunction. As multiple concurrent threads executes same code in same time, a little ahead or back.., Use IntentService instead...


    Main and most Important difference between a Service and IntentService is, Even if Intent Service is called 10 times...

    1. It will start execution of first request..
    2. If new call to that IntentService is made, then it will remain in waiting... As IntentService is being run...
    3. When it completes first calls execution.., the second request in waiting will start executing IntentService.

    Possible Simplest IntentService :

    public class MyWorkerThread extends IntentService
    {
    
        public MyWorkerThread()
        {
            super("SMSEngine");
            Log.d("MyWorkerThread : ", "\nCreated...");
        }
    
        @Override
        protected void onHandleIntent(Intent intent)
        {
            // Your background code goes here..
        }
    }