Question

I have a service that is started when the main application starts. I call the Service using this code

Intent serviceIntent = new Intent(this, SMS_Listener_Service.class);
startService(serviceIntent);

The Service itself has the following main notable code

public class SMS_Listener_Service extends Service {
    @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        if (!blnAutoSyncisEnabled) {
            stopSelf();
            return 0;
        } else {
            return START_STICKY;

    }
        private class MyContentObserver extends ContentObserver {

            public MyContentObserver() {
                super(null);
            }

            @Override
            public void onChange(boolean selfChange) {
                super.onChange(selfChange);
                //pause for 3 seconds and see if the counter changes. 
                 if it goes past 5  transactions then start processing and start a timer
                TaskToRunAfter3Seconds();
                intTimesCalled = intTimesCalled + 1;
            }

        }

       }
        private void TaskToRunAfter3Seconds() {

        try {
            //calls the ReadTrandactions intentService that parses sms messages
            Intent intent = new Intent(context,   ReadTransactionsForSERVICE.class);
            startService(intent);

        } catch (NumberFormatException e) {

            BugSenseHandler.sendException(e);
        }
}


}

Then we have the called intent Service in which i handle the work in the OnHandleIntent Method

public class ReadTransactionsForSERVICE extends IntentService {

    public ReadTransactionsForSERVICE() {
        super("ReadTransactionsForSERVICE");
     }
   protected void onHandleIntent(Intent intent) {
        //Initialize stuff
       try {
        //do the main work here.
       } catch (Exception e) {

        BugSenseHandler.sendException(e);
         return;
       }

    }


}

My question is, Is my implementation sound? Ie is it ok to call an IntentService from a BroadcastReceiver in a Service?

I ask this because , My Service hangs in the most odd fashion and I suspect the IntentService called from Service could be the issue. (I asked a similar question earlier but got no response. this one is more detailed. 1: https://stackoverflow.com/posts/21057789/edit)

For some reason it Hangs and cannot be stopped even by memory or task managers. Physically tapping "Stop" in the service itself does nothing.

enter image description here

Uninstalling the app doesn't work either because when you go the running processes you see an item "Unknown process.....restarting" and if you try kill that then the applications manager generates an error ie "Settings has stopped" but on return the Unknown process is still there.

If you then Install the app again while the above is showing, the service never starts. it again remains in the "restarting" mode. The only cure is to Restart the Phone itself. (cold boot)

The above has been observed only on android 4.3 and above. Lower versions don't seem to have this issue.

Thanks and looking forward to some help.

I call the service from 3 points depending on the scenario. first is on application startup Where I check if the Service is up and if not i start it.

Second is from the BroadcastReceiver

public class SMSNotifyStarter extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Intent service = new Intent(context, SMS_Listener_Service.class);
        context.startService(service);
        //(this,"Boot Complete Recieved and Service Started.");
    }
}

and finally from a network State change. ie if a new internet connection is made active (Wifi or Mobile) I check for new Transactions. code here

public class NetworkChangeReceiver extends BroadcastReceiver {
    Context ctx;
    @Override
    public void onReceive(final Context context, final Intent intent) {
        ctx = context;
        int status = NetworkUtil.getConnectivityStatusString(context);
        if (status == 1 || status == 2) { //means wifi or mobile is active
        blnSyncAllowed = GSR.ReadSharedPreferencesBool(ctx, 
                             GSR.PrefsFileName,"SYNC_ALLOWED", true);

        if (blnSyncAllowed)) {
            Intent intentx = new Intent(context, ReadTransactionsForSERVICE.class);
            intentx.putExtra("CalledByWakeOnConnectionFound", "WakeOnConnectionFound");
            context.startService(intentx);

          }
        }

       //Toast.makeText(context, status, Toast.LENGTH_LONG).show();
    }


}

Manifest entries

    <receiver
        android:name="com.myappName.NetworkChangeReceiver"
        android:label="NetworkChangeReceiver">
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
        </intent-filter>
    </receiver>

    <receiver android:name="com.myappName.SMSNotifyStarter">
        <intent-filter>
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>


    <service
        android:name="com.myappName.SMS_Listener_Service"
        android:enabled="true"
        android:icon="@drawable/myAppIcon"
        android:label="myAppManager">

        <intent-filter>
            <action android:name="com.myappName.SMS_Listener_Service" />
        </intent-filter>
    </service>
    <service android:name="myappName.ReadTransactionsForSERVICE">
   </service>
Was it helpful?

Solution

I would ask this as a comment, but I just got started here. Have you registered your broadcast receiver and your services in the manifest?

For the service/intentservice:

<service
    android:name="your service path"
    android:exported="false" > <!--if you only want to call it from within your app-->
</service>

And for the broadcast receiver:

<receiver android:name="your receiver path"
    android:exported="false" <!--if you only want to call it from within your app-->
    <intent-filter>
        <action android:name="the action you're sending" />
    </intent-filter>
</receiver>

Also, I'm not sure how you're filtering your intents in your intent service, since you don't have an action in the intent.

intent.setAction("action");

Then you can look for this action in the onHandleIntent() method. I suppose it's okay if you just have the one intent, but otherwise, I'd recommend adding this as well. Please put debug points in the code to see if you're reaching the onHandleIntent method() as well.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top