0

When I close my application, the service that had been started is supposed to continue running in the background. For some reason, the application crashes and throws a NullPointerException upon closing it.

I am using a MQTTConstants class to keep all the Constants in one place, and within that class I have a Hashset declared, which is then modified throughout the life of the application.

Is it possible that by closing the app, this information is being cleared? Although the service is never disconnected.

The service would continue to work off of this TOPIC_SET as it continues to run in the background.

  public static HashSet<String> TOPIC_SET = new HashSet<String>();

STACK TRACE

02-20 14:14:30.620: E/AndroidRuntime(14753): FATAL EXCEPTION: MQTTservice 02-20 14:14:30.620: E/AndroidRuntime(14753): Process: com.l.ltestmqtt, PID: 14753 02-20 14:14:30.620: E/AndroidRuntime(14753): java.lang.NullPointerException 02-20 14:14:30.620: E/AndroidRuntime(14753): at com.l.ltestmqtt.MQTTService.handleStartAction(MQTTService.java:315) 02-20 14:14:30.620: E/AndroidRuntime(14753): at com.l.ltestmqtt.MQTTService.handleStart(MQTTService.java:231) 02-20 14:14:30.620: E/AndroidRuntime(14753): at com.l.ltestmqtt.MQTTService$2.run(MQTTService.java:196) 02-20 14:14:30.620: E/AndroidRuntime(14753): at java.lang.Thread.run(Thread.java:841)

Here are the methods that are named within the Stack Trace

handleStart

synchronized void handleStart(Intent intent, int startId) {
    // before we start - check for a couple of reasons why we should stop
    Log.e("SERVICE", "----------HANDLESTART()-----------");

    if (mqttClient == null) {
      // we were unable to define the MQTT client connection, so we stop
      // immediately - there is nothing that we can do
      stopSelf();
      return;
    }

    ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
    if (cm.getBackgroundDataSetting() == false) // respect the user's request not to use data!
    {
      // user has disabled background data
      connectionStatus = MQTTConnectionStatus.NOTCONNECTED_DATADISABLED;

      // update the app to show that the connection has been disabled
      broadcastServiceStatus("Not connected - background data disabled");

      // we have a listener running that will notify us when this
      // preference changes, and will call handleStart again when it
      // is - letting us pick up where we leave off now
      return;
    }
    if (!handleStartAction(intent)) {
      // the Activity UI has started the MQTT service - this may be starting
      // the Service new for the first time, or after the Service has been
      // running for some time (multiple calls to startService don't start
      // multiple Services, but it does call this method multiple times)
      // if we have been running already, we re-send any stored data
      rebroadcastStatus();
      rebroadcastReceivedMessages();
    }

    // if the Service was already running and we're already connected - we
    // don't need to do anything
    if (isAlreadyConnected() == false) {
      // set the status to show we're trying to connect
      connectionStatus = MQTTConnectionStatus.CONNECTING;

      // we are creating a background service that will run forever until
      // the user explicity stops it. so - in case they start needing
      // to save battery life - we should ensure that they don't forget
      // we're running, by leaving an ongoing notification in the status
      // bar while we are running
      NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
      Notification notification =
          new Notification(R.drawable.ic_launcher, "MQTT", System.currentTimeMillis());
      notification.flags |= Notification.FLAG_ONGOING_EVENT;
      notification.flags |= Notification.FLAG_NO_CLEAR;
      Intent notificationIntent = new Intent(this, MQTTNotifier.class);
      PendingIntent contentIntent =
          PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
      notification.setLatestEventInfo(this, "MQTT", "MQTT Service is running", contentIntent);
      nm.notify(MQTTConstants.MQTT_NOTIFICATION_ONGOING, notification);


      // before we attempt to connect - we check if the phone has a
      // working data connection
      if (isOnline()) {
        // we think we have an Internet connection, so try to connect
        // to the message broker
        if (connectToBroker()) {
          // we subscribe to a topic - registering to receive push
          // notifications with a particular key
          // in a 'real' app, you might want to subscribe to multiple
          // topics - I'm just subscribing to one as an example
          // note that this topicName could include a wildcard, so
          // even just with one subscription, we could receive
          // messages for multiple topics


          //subscribe to initial TOPIC_SET topics, ie device_id_topic, all_topic
          subscribeToAllTopics();
          //subscribeToTopic(topicName);
        }
      } else {
        // we can't do anything now because we don't have a working
        // data connection
        connectionStatus = MQTTConnectionStatus.NOTCONNECTED_WAITINGFORINTERNET;

        // inform the app that we are not connected
        broadcastServiceStatus("Waiting for network connection");
      }
    }

    // changes to the phone's network - such as bouncing between WiFi
    // and mobile data networks - can break the MQTT connection
    // the MQTT connectionLost can be a bit slow to notice, so we use
    // Android's inbuilt notification system to be informed of0
    // network changes - so we can reconnect immediately, without
    // having to wait for the MQTT timeout
    if (netConnReceiver == null) {
      netConnReceiver = new NetworkConnectionIntentReceiver();
      registerReceiver(netConnReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));

    }

    // creates the intents that are used to wake up the phone when it is
    // time to ping the server
    if (pingSender == null) {
      pingSender = new PingSender();
      registerReceiver(pingSender, new IntentFilter(MQTTConstants.MQTT_PING_ACTION));
    }
  }

handleStartAction

  private boolean handleStartAction(Intent intent) {
String action = intent.getAction();

if (action == null) {
  return false;
}

if (action.equalsIgnoreCase(MQTTConstants.MQTT_SUBSCRIBE_TOPIC_INTENT)) {
  handleSubscribeTopicIntent(intent);
}

if (action.equalsIgnoreCase(MQTTConstants.MQTT_PUBLISH_MSG_INTENT)) {
  handlePublishMessageIntent(intent);
}

if (action.equalsIgnoreCase(MQTTConstants.MQTT_UNSUBSCRIBE_TOPIC_INTENT)) {
  handleUnsubscribeTopicIntent(intent);
}

return true;
}

UPDATES: The problem exists within the handleStart() method. If I comment this if (!handleStartAction(intent)) { the issue no longer occurs.

FOR ρяσѕρєя K The service is started inside MQTTNotifier Activity using this

    MQTTServiceDelegate.startService(this);

which references this method inside the MQTTServiceDelegateClass

public static void startService(Context context) {
    Intent svc = new Intent(context, MQTTService.class);
    context.startService(svc);
  }
Coova
  • 1,818
  • 5
  • 36
  • 63

1 Answers1

0

I have solved the issue, I will mark this as the answer unless someone is able to provide a better solution.

I ran a quick test to see if the intent was == null, and if it was I just logged it, otherwise I processed the code.

  private boolean handleStartAction(Intent intent) {
    if (intent == null) {
      Log.e("NULL INTENT", "***************NULL INTENT**************");
    } else {
      String action = intent.getAction();

      if (action == null) {
        return false;
      }

      if (action.equalsIgnoreCase(MQTTConstants.MQTT_SUBSCRIBE_TOPIC_INTENT)) {
        handleSubscribeTopicIntent(intent);
      }

      if (action.equalsIgnoreCase(MQTTConstants.MQTT_PUBLISH_MSG_INTENT)) {
        handlePublishMessageIntent(intent);
      }

      if (action.equalsIgnoreCase(MQTTConstants.MQTT_UNSUBSCRIBE_TOPIC_INTENT)) {
        handleUnsubscribeTopicIntent(intent);
      }
    }

    return true;
  }
Coova
  • 1,818
  • 5
  • 36
  • 63