簡體   English   中英

關閉應用程序並且服務仍在運行后的NullPointerException

[英]NullPointerException after Closing App with Service still running

當我關閉我的應用程序時,已啟動的服務應該繼續在后台運行。 由於某種原因,應用程序崩潰並在關閉它時拋出NullPointerException。

我正在使用MQTTConstants類將所有常量保存在一個位置,並且在該類中我聲明了一個Hashset,然后在應用程序的整個生命周期中對其進行修改。

是否有可能通過關閉應用程序,此信息被清除? 雖然服務永遠不會斷開。

該服務將繼續在此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):進程: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):在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)

以下是在堆棧跟蹤中命名的方法

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)) {問題不再發生。

FORρяσѕρєяk上的服務MQTTNotifier活動中使用此啟動

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM