private void startMainApp(final boolean uptodate) {
    Log.d(TAG, "Main startup");

    if (preferences.settingsNeedSending()) {
      Log.d(TAG, "Settings are not saved, odd");
      sendSettings();
    }

    final long now = new Date().getTime();

    final Callback<List<Channel>> dataAccessCallback =
        new Callback<List<Channel>>() {
          public void doStuff(List<Channel> param) {
            backgroundOperationEnded();
            synchronized (channelsLock) {
              channels = param;
              refreshUi();
            }
          }
        };

    final DataFetcherTask dataFetcherTask =
        new DataFetcherTask(
            this,
            preferences.getEncryptionPassword(),
            preferences.getLastFetchTime(),
            new Callback<DataFetchResult>() {
              // TODO: Move this into its own activity, so orientation changes work correctly
              public void doStuff(DataFetchResult param) {
                backgroundOperationEnded();
                preferences.setLastFetchTime(now);

                if (param.getException() != null) {
                  handleNetworkException(param.getException());
                  return;
                }

                if (param.getResponse().getServerMessage() != null
                    && param.getResponse().getServerMessage().length() > 0) {
                  MessageBox.Show(
                      IrssiNotifierActivity.this,
                      null,
                      param.getResponse().getServerMessage(),
                      null);
                }

                if (param.getMessages().isEmpty()) {
                  return;
                }

                DataAccessTask task =
                    new DataAccessTask(IrssiNotifierActivity.this, dataAccessCallback);
                List<IrcMessage> messages = param.getMessages();
                TaskExecutor.executeOnThreadPoolIfPossible(
                    task, messages.toArray(new IrcMessage[messages.size()]));
                backgroundOperationStarted();
              }
            });

    runOnUiThread(
        new Runnable() {
          @Override
          public void run() {
            refreshUi();

            if (!uptodate
                && preferences.isPullMechanismInUse()
                && LicenseHelper.isPlusVersion(IrssiNotifierActivity.this)) {
              TaskExecutor.executeOnThreadPoolIfPossible(dataFetcherTask);
              backgroundOperationStarted();
            }

            DataAccessTask datask =
                new DataAccessTask(IrssiNotifierActivity.this, dataAccessCallback);
            TaskExecutor.executeOnThreadPoolIfPossible(datask);
            backgroundOperationStarted();

            if (LicenseHelper.isPlusVersion(IrssiNotifierActivity.this)) {
              checkLicense();
            }
          }
        });
  }