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);
}