关闭带有服务的应用程序后出现 NullPointerException 运行
NullPointerException after Closing App with Service still running
当我关闭我的应用程序时,已经启动的服务应该在后台继续 运行ning。由于某种原因,应用程序崩溃并在关闭时抛出 NullPointerException。
我正在使用 MQTTConstants class 将所有常量保存在一个地方,并且在其中 class 我声明了一个哈希集,然后在应用程序的整个生命周期中对其进行修改。
有没有可能关闭应用程序,这些信息就被清除了?虽然服务一直没断。
该服务将继续在后台工作 TOPIC_SET,因为它会在后台继续 运行。
public static HashSet<String> TOPIC_SET = new HashSet<String>();
堆栈跟踪
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.run(MQTTService.java:196)
02-20 14:14:30.620: E/AndroidRuntime(14753): at
java.lang.Thread.run(Thread.java:841)
以下是在堆栈跟踪中命名的方法
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;
}
更新: handleStart() 方法中存在问题。如果我对此发表评论 if (!handleStartAction(intent)) {
,问题将不再发生。
对于 ρяσѕρєя K
使用此
在 MQTTNotifier Activity 中启动该服务
MQTTServiceDelegate.startService(this);
在 MQTTServiceDelegateClass 中引用此方法
public static void startService(Context context) {
Intent svc = new Intent(context, MQTTService.class);
context.startService(svc);
}
我已经解决了这个问题,除非有人能够提供更好的解决方案,否则我会将此标记为答案。
我 运行 快速测试以查看意图是否为 == null,如果是,我只是记录它,否则我处理代码。
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;
}
当我关闭我的应用程序时,已经启动的服务应该在后台继续 运行ning。由于某种原因,应用程序崩溃并在关闭时抛出 NullPointerException。
我正在使用 MQTTConstants class 将所有常量保存在一个地方,并且在其中 class 我声明了一个哈希集,然后在应用程序的整个生命周期中对其进行修改。
有没有可能关闭应用程序,这些信息就被清除了?虽然服务一直没断。
该服务将继续在后台工作 TOPIC_SET,因为它会在后台继续 运行。
public static HashSet<String> TOPIC_SET = new HashSet<String>();
堆栈跟踪
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.run(MQTTService.java:196) 02-20 14:14:30.620: E/AndroidRuntime(14753): at java.lang.Thread.run(Thread.java:841)
以下是在堆栈跟踪中命名的方法
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;
}
更新: handleStart() 方法中存在问题。如果我对此发表评论 if (!handleStartAction(intent)) {
,问题将不再发生。
对于 ρяσѕρєя K 使用此
在 MQTTNotifier Activity 中启动该服务MQTTServiceDelegate.startService(this);
在 MQTTServiceDelegateClass 中引用此方法
public static void startService(Context context) {
Intent svc = new Intent(context, MQTTService.class);
context.startService(svc);
}
我已经解决了这个问题,除非有人能够提供更好的解决方案,否则我会将此标记为答案。
我 运行 快速测试以查看意图是否为 == null,如果是,我只是记录它,否则我处理代码。
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;
}