There are a few different approaches you can take, the easiest one being to just force them to log in every time they use your app, but that’s a pretty horrible user experience. Typically, you should be saving some kind of token that was returned when the user logs in and storing it somewhere outside the lifecycle of the app.

Once you have the token, you can keep them logged in until the token expires. In the past, what I’ve done is either set the LoginActivity or MainActivity as main in the manifest. If the LoginActivity is set as main, I check if there is a token stored, and if so, start MainActivity and call finish. If instead MainActivity is set as main, I do a check if there is no token stored, and if so start the LoginActivity and call finish.

This approach works, but it’s a bit clunky and slow. I discovered another approach, using the NoDisplay theme. With it, I create another activity called MainEmptyActivity. It looks like this:

public class MainEmptyActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent activityIntent;

        // go straight to main if a token is stored
        if (Util.getToken() != null) {
            activityIntent = new Intent(this, MainActivity.class);
        } else {
            activityIntent = new Intent(this, LoginActivity.class);
        }

        startActivity(activityIntent);
        finish();
    }
}

Then I add it to the manifest as follows:

<activity
    android:name=".activity.MainEmptyActivity"
    android:theme="@android:style/Theme.NoDisplay">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

As part of this flow, it’s important to consider the token may expire. If it does, you should send them back to the login activity and delete the token from your storage. Usually, you would check for a 401 from any request and consider that as a token expired, but responses may vary.

You can also apply this approach to any number of states, the two states of login and main are simply the most common. You can do whatever checks you want in your empty activity and transition from there.

Alternatively, you can use a splash screen instead of the NoDisplay theme.

Whether you keep the display UI free or add in a splash screen is up to you, though. The flow remains the same either way.