47

Is there a way to dynamically change the starting activity in Android based upon a conditionally? What I attempted to do (that didn't work) was the following:

  1. remove the LAUNCHER category as defined in my AndroidManifest.xml
  2. create a custom Application class that the app uses
  3. override the onCreate method of my Application class to define some code like the following:

.

if (condition) {
    startActivity(new Intent(this, MenuActivity.class));
} else {
    startActivity(new Intent(this, LoginActivity.class));
}
Matt Huggins
  • 81,398
  • 36
  • 149
  • 218

2 Answers2

59

Why not have an initial Activity with no UI that checks the condition in its onCreate, then launches the next Activity, then calls finish() on itself? I've never called finish() from within onCreate() though, so I'm not sure if this will work.

EDIT
Seems to work fine. Here's some code to make it clearer.
Initial Activity:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Intent intent;
    if (condition) {
       intent = new Intent(this, ClassA.class);
    } else {
       intent = new Intent(this, ClassB.class);
    }
    startActivity(intent);
    finish();
    // note we never called setContentView()
}

Other Activity:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
}
dave.c
  • 10,910
  • 5
  • 39
  • 62
  • Can you have an Activity with no UI? I thought the whole point of an Activity was to display something to the user, but perhaps I need to do some re-reading on Android basics... – Matt Huggins Jan 31 '11 at 22:00
  • 1
    @Matt Huggins I just tried it in my scratch workspace and it seems to work fine. – dave.c Jan 31 '11 at 22:08
  • 1
    That is the whole point of an activity, but there are plenty of ways around this. I think what dave meant was just don't declare a UI. There's nothing requiring you to call setContentView or anything. Just do your check, start your next activity, and be on with it. – Falmarri Jan 31 '11 at 22:09
  • @Falmarri exactly. My post was poorly worded – dave.c Jan 31 '11 at 22:10
  • You solved my problem of selecting a special activity for the first run. Thank you ! – Vincent Cantin May 26 '12 at 19:12
  • Most probably this is the best way. Although the API should have allowed to do this programmatically from a main `Application`'s `onCreate` without declaring the activity in the manifest. It would have been cleaner for MVC approaches IMHO. – Mister Smith Aug 27 '13 at 10:35
  • 1
    I can still see the title of the initial activity briefly even though I don't call `setContentView`. The title comes from `AndroidManifest.xml`. – Monstieur May 26 '14 at 04:57
  • @Locutus re-read what you just said: "I can see the title, but I don't call `set` **Content** `View`"... so you didn't set a content, but the `Activity` still has a `Window`, which contains more than the `contentView`. – TWiStErRob Aug 21 '14 at 11:30
  • 3
    @TWiStErRob The point is this approach is wrong. No temporary `Window` should be created at all. – Monstieur Aug 21 '14 at 18:24
  • Another problem is that both "start activities" would share the same theme – Snicolas Apr 30 '15 at 17:19
8

Here's what I personally did for one of my small mobile projects. Instead of creating a separate, screen-less Activity where the condition is and which launches the corresponding screen, I put the condition in one Activity and did a dynamic setContentView(), as in:

if (!userIsLoggedIn) {
    setContentView(R.layout.signup);
} else {
    setContentView(R.layout.homescreen);
}

Two important notes to this approach:

1: Instead of writing that in onCreate(), you want to put the decision-making inside onResume() precisely because the latter is always called whenever the screen needs to be displayed in front. You can see that from the Android activity life cycle. So if, for example, the user just downloaded my app and launched it for the first time, because no user is logged in, she will be led to the signup page. When she's done signing up and for some reason presses the HOME button (not BACK, which exits the app altogether!) and then resumes the app, the layout that she will see is already the home screen's. If I put the conditional inside onCreate(), what would have been displayed is the sign up screen because according to the life cycle, it doesn't go back to onCreate() when bringing back an app to the front.

2: This solution is ideal only if merging the functionalities of those two Activities would not produce a long diabolical block of code. Like I said, my project was a small one (its primary feature occurs in the background), so that single dynamic Activity didn't have too much in it. The screen-less Activity is definitely the way to go if you need your code to be more human-readable.

Matthew Quiros
  • 13,385
  • 12
  • 87
  • 132
  • 3
    +1 for sharing an alternate method. :) As you already mentioned, my only concern with this method is that each view might require a largely different set of underlying code, which would make the Activity bulky and incongruent. – Matt Huggins Aug 03 '12 at 13:41
  • 1
    @MattHuggins this solution probably works best if you use `Fragment`s which encapsulates the `contentView` and the "largely different set of underlying code". – TWiStErRob Aug 21 '14 at 11:32