@Override
  public void onCreate() {
    ACRA.init(this);

    App.init(this);

    final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
    CalculatorPreferences.setDefaultValues(preferences);

    preferences.registerOnSharedPreferenceChangeListener(this);

    setTheme(preferences);

    super.onCreate();

    final AndroidCalculator calculator = new AndroidCalculator(this);

    final EditorTextProcessor editorTextProcessor = new EditorTextProcessor();

    Locator.getInstance()
        .init(
            calculator,
            new AndroidCalculatorEngine(this),
            new AndroidCalculatorClipboard(this),
            new AndroidCalculatorNotifier(this),
            new AndroidCalculatorHistory(this, calculator),
            new AndroidCalculatorLogger(),
            new AndroidCalculatorPreferenceService(this),
            new AndroidCalculatorKeyboard(this, new CalculatorKeyboardImpl(calculator)),
            new AndroidCalculatorPlotter(this, new CalculatorPlotterImpl(calculator)),
            editorTextProcessor);

    editorTextProcessor.init(this);

    listeners.add(new CalculatorActivityLauncher());
    for (CalculatorEventListener listener : listeners) {
      calculator.addCalculatorEventListener(listener);
    }

    calculator.addCalculatorEventListener(broadcaster);

    Locator.getInstance().getCalculator().init();

    BillingDB.init(CalculatorApplication.this);

    if (withAds) {
      AdsController.getInstance()
          .init(
              this,
              ADMOB_USER_ID,
              AD_FREE_PRODUCT_ID,
              new BillingController.IConfiguration() {

                @Override
                public byte[] getObfuscationSalt() {
                  return new byte[] {
                    81, -114, 32, -127, -32, -104, -40, -15, -47, 57, -13, -41, -33, 67, -114, 7,
                    -11, 53, 126, 82
                  };
                }

                @Override
                public String getPublicKey() {
                  return CalculatorSecurity.getPK();
                }
              });
    }

    BillingController.registerObserver(new DefaultBillingObserver(this, null));

    // init billing controller
    new Thread(
            new Runnable() {
              @Override
              public void run() {
                BillingController.checkBillingSupported(CalculatorApplication.this);
                AdsController.getInstance().isAdFree(CalculatorApplication.this);

                try {
                  // prepare engine
                  Locator.getInstance().getEngine().getMathEngine0().evaluate("1+1");
                  Locator.getInstance().getEngine().getMathEngine0().evaluate("1*1");
                } catch (Throwable e) {
                  Log.e(TAG, e.getMessage(), e);
                }
              }
            })
        .start();

    Locator.getInstance().getLogger().debug(TAG, "Application started!");
    Locator.getInstance().getNotifier().showDebugMessage(TAG, "Application started!");
  }