@Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    accountDb = DependencyInjector.getAccountDb();
    preferences = PreferenceManager.getDefaultSharedPreferences(this);

    // Apply theme based on user's preference.
    darkModeEnabled = preferences.getBoolean(KEY_DARK_MODE_ENABLED, false);
    setTheme(
        darkModeEnabled
            ? R.style.AuthenticatorTheme_NoActionBar_Dark
            : R.style.AuthenticatorTheme_NoActionBar);

    // Use a different (longer) title from the one that's declared in the manifest (and the one that
    // the Android launcher displays).
    setTitle(R.string.app_name);

    totpCounter = otpProvider.getTotpCounter();
    totpClock = otpProvider.getTotpClock();

    setContentView(R.layout.main);

    toolbar = (Toolbar) findViewById(R.id.authenticator_toolbar);
    setSupportActionBar(toolbar);

    // If the number of accounts is bigger than 0, we assume the user has completed the onboarding
    // experience (i.e. for upgrading users who have already added accounts into the app).
    if (getAccountCount() > 0) {
      preferences.edit().putBoolean(KEY_ONBOARDING_COMPLETED, true).commit();
    }

    // restore state on screen rotation
    @SuppressWarnings("deprecation") // TODO: refactor to use savedInstanceState instead
    Object savedState = getLastCustomNonConfigurationInstance();
    if (savedState != null) {
      users = (PinInfo[]) savedState;
      // Re-enable the Get Code buttons on all HOTP accounts, otherwise they'll stay disabled.
      for (PinInfo account : users) {
        if (account.isHotp()) {
          account.setIsHotpCodeGenerationAllowed(true);
        }
      }
    }

    if (savedInstanceState != null) {
      firstAccountAddedNoticeDisplayRequired =
          savedInstanceState.getBoolean(KEY_FIRST_ACCOUNT_ADDED_NOTICE_DISPLAY_REQUIRED, false);
    }

    userList = (EmptySpaceClickableDragSortListView) findViewById(R.id.user_list);

    // Long-tapping on a list item starts the Contextual Action Bar for
    // that item.
    registerContextualActionBarForUserList();

    // Short-tapping on a list item generates the next code for HOTP accounts and does nothing for
    // TOTP accounts. Note that, while the Contextual Action Bar is displayed, short-tapping on a
    // list item will not generate codes and instead mark the tapped item as checked.
    userList.setOnItemClickListener(
        new OnItemClickListener() {
          @Override
          public void onItemClick(AdapterView<?> parent, View row, int position, long itemId) {
            // Each item in DragSortListView is wrapped with DragSortItemView.
            // Iterating the children to find the enclosed UserRowView
            DragSortItemView dragSortItemView = (DragSortItemView) row;
            View userRowView = null;
            for (int i = 0; i < dragSortItemView.getChildCount(); i++) {
              if (dragSortItemView.getChildAt(i) instanceof UserRowView) {
                userRowView = dragSortItemView.getChildAt(i);
              }
            }
            if (userRowView == null) {
              return;
            }
            NextOtpButtonListener clickListener = (NextOtpButtonListener) userRowView.getTag();
            View nextOtp = userRowView.findViewById(R.id.next_otp);
            if ((clickListener != null) && nextOtp.isEnabled()) {
              clickListener.onClick(userRowView);
            }
            userList.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
          }
        });
    userList.setOnEmptySpaceClickListener(() -> unselectItemOnList());

    contentNoAccounts = findViewById(R.id.content_no_accounts);
    contentAccountsPresent = findViewById(R.id.content_accounts_present);

    refreshLayoutByUserNumber();
    refreshOrientationState();

    findViewById(R.id.add_account_button)
        .setOnClickListener(
            new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                if (onboardingCompleted) {
                  addAccount();
                } else {
                  displayHowItWorksInstructions();
                }
              }
            });

    FloatingActionButton addAccountFab = (FloatingActionButton) findViewById(R.id.add_account_fab);
    addAccountFab.setOnClickListener(
        new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            showModalBottomSheet();
          }
        });

    // Make sure the Fab is always on top of the pin code list
    addAccountFab.bringToFront();
    contentAccountsPresent.invalidate();

    findViewById(R.id.first_account_message_button_done)
        .setOnClickListener(
            new OnClickListener() {
              @Override
              public void onClick(View view) {
                dismissFirstAccountAddedNoticeDisplay();
              }
            });

    userAdapter = new PinListAdapter(this, R.layout.user_row, users);

    userList.setAdapter(userAdapter);
    userList.setDropListener(
        new DropListener() {
          @Override
          public void drop(int from, int to) {
            userAdapter.notifyDataSetChanged();
          }
        });
    userList.setDragListener(
        new DragListener() {
          @Override
          public void drag(int from, int to) {
            if (from == to) {
              return;
            }
            List<AccountIndex> accounts = accountDb.getAccounts();
            AccountIndex firstIndex = accounts.get(from);
            AccountIndex secondIndex = accounts.get(to);
            try {
              // drag callback is fired in a worker thread, swapping the Ids doesn't affect the UI
              // thread.
              accountDb.swapId(firstIndex, secondIndex);
            } catch (AccountDbIdUpdateFailureException e) {
              Toast.makeText(
                      getApplicationContext(), R.string.accounts_reorder_failed, Toast.LENGTH_SHORT)
                  .show();
            }
            PinInfo.swapIndex(users, from, to);
          }
        });
    DragItemController dragItemController = new DragItemController(userList, this);
    dragItemController.setStartDraggingListener(
        new DragItemController.StartDraggingListener() {
          @Override
          public void startDragging() {
            unselectItemOnList();
          }
        });
    userList.setFloatViewManager(dragItemController);
    userList.setOnTouchListener(dragItemController);

    if (savedInstanceState == null) {
      // This is the first time this Activity is starting (i.e., not restoring previous state which
      // was saved, for example, due to orientation change)
      handleIntent(getIntent());
    }
  }
Called when the activity is first created.
java/com/google/android/apps/authenticator/AuthenticatorActivity.java