I have two activities but I want to apply a condition on application start, if one is true then start first activity else start second activity. Right now I am doing it by starting a third activity displaying some welcome stuff and examining the value in background..then appropriate activity gets called. I think there must be some standard way to do this. Peace.
Since you need to specify starting activity in manifest, you can always start first activity, check your condition on onCreate() and if you need to start second one - start second one and call finish() for the first activity.
Otherwise usually people use splash activity to check all the conditions at the startup (which is your current solution).
There's no need for a third Activity to check the condition.
If you simply have your MAIN/LAUNCHER Activity check on the condition as the very first thing it does in onCreate(...) (but after calling super.onCreate(...)), it can either continue or call startActivity(...) for the other Activity and immediately call finish() to self-terminate.
That way the first Activity will never be seen if the condition dictates the second Activity should be started.
Example..
public class FirstActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Don't even set the content view at this point
// we want to be invisible for the moment
// Pseudo-code check for condition
if (!runMe) {
Intent i = new Intent(this, SecondActivity.class);
startActivity(i);
finish();
}
else {
// Continue as normal
setContentView(R.layout.main);
...
}
}
}
Related
I have application and when I navigate back using Intent and startActivity(), views are null, onCreate() is called and activities are re-initialized. Why is that and how to bypass it?
I navigate back to activity like that:
#Override
public void onBackPressed() {
if (this.getClass() == XXX.class) {
Intent i = new Intent(this, YYY.class);
startActivity(i); //<-- activity restarts
return;
}
}
super.onBackPressed();
}
I use ActionbarSherlock, so I have activity with ActionBar initialization and every single activity just extends it. The way I navigate back to activity is described in this activity.
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
initUIComponents();
setListeners();
resetProgress();
}
and initUI() initializes UI.
EDIT
What I mean, how can I go back to previously created activity (not the one that is called via onBackPressed) and not recreate it? I use startActivity(), but apparently it recreates the whole thing
If you want that when you press back, you want to show the previous screen, then you don't have to do it in your code. Android Runtime internally maintains the stack, and will take care of showing the last-shown-activity when you press back. No need to handle it via onBackPressed()
However, if you want something other than this default action, that is when you should use onBackPressed(). Else, just let Android handle it.
So, in your application, if Activity 1 calls Activity 2, and user presses back, then the default action would be to show Activity 1 again. Don't override the onBackPressed() method
Edit:
For a custom flow of activities, you'll have to build the logic yourself. You need to override onRestart() in Activity 1, and onStop() in Activity 3. That way, onCreate won't be called again. By your logic, I mean, flags to keep track of which activity you're in, checking those flags, and calling the desired activity from there.
Edit 2:
This previous SO question, answers what you need:
Android Activity management , which suggests setting the flag FLAG_ACTIVITY_REORDER_TO_FRONT on the intent, and then calling startActivity()
Check out Android activity stack management using Intent flags for other stack reordering options: Stack management
I want to reload an activity from stack.
I use startActivity() to start new activities. When I'm on Activity D I want to reload Activity A and not start a new Intent. I can't use startActivity() when calling A from D because it will fire onCreate() which starts a thread to fetch some data.
EDIT: Updated the stack.
If I use FLAG_ACTIVITY_REORDER_TO_FRONT it calls the onCreate() method again.
Following is my scenario.
Login Activity ̣→ Activity A → Activity B → Activity C → Activity D → Activity A
How do I avoid onCreate() being called?
You have to take a totally different approach. It doesn't matter if you start your Activity with startActivity() or startActivityForResult() because onCreate(), onStart() and onResume() will be called when you start an Activity.
Now if you have a method in your Activity class that starts another thread to do some work then you have to work with flags. If your Activity requires to automatically start the thread on first execution then you have to wrap it around an if clause to check for a flag you set when it is first run.
The idea is to have your Activity set a boolean to true in either your Application instance or SharedPreferences when the thread is first executed. When you come back to that Activity and don't want that thread to be run automatically due to onCreate() being called then you have to wrap your calling code around some if clause like in the example below.
Here is an example.
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
// Other stuff
if (!YourApplicationInstance.wasCalled) {
// Run your thread or do something else you want to do only once.
// Set the wasCalled flag to true to not run this code again
// if onCreate() is called a second time.
YourApplicationInstance.wasCalled = true;
}
}
You'll have to read Using Application context everywhere? to understand how to implement my pseudo class YourApplicationInstance.
The following is not true. startActivityForResult() and startActivity() only differ in the return target of the called Activity
try using startActivityForResult() rather than
startActivity(). I believe this does not completely end the activity and start it again. I
would recommend using this link in order to further read on how to implement such a method.
So point 2 of #Kgrover does not hold too.
The Intent flag http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_REORDER_TO_FRONT does exactly this.
Keep an eye out on the Intent flags whenever you have requirements centered around Activity transitions. The system has excellent support.
This is equivalent to Sam Quest's solution, the only difference being that if you set the launchMode, the stack-behavior of your Activity is hardcoded i.e. your Activity A is always in the singleTask mode.
there is tag called launchMode for activity in the manifest. checkout this link. and this will not call onCreate but it will call onNewIntent, where you can reinitialize you stuff.
1) Although I am not sure, you could try using startActivityForResult() rather than startActivity(). I believe this does not completely end the activity and start it again. I would recommend using this link in order to further read on how to implement such a method.
2) Alternatively, when you go from activity D -> A, continue to use startActivity(), but pass in a dummy extra. Then in activity A, use an if statement:
if(!(this.getIntent().hasExtra("dummyStringExtra")) {
//fire the data thread here
}
Cheers. I hope this helps.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
this.finish();
return true;
}
return super.onOptionsItemSelected(item);
}
This will kill the child activity. So parent activity is not recreated
I want to start a Activity A from status bar notification, When the activity A is already in front then i want to finish that and fresh start activity A. How can i do this?
Review the documentation on creating Status Bar Notifications. This definitely covers starting and Activity from a Notification using an Intent and PendingIntent.
http://developer.android.com/guide/topics/ui/notifiers/notifications.html
As for if the Activity is already running, finish it and start it freshly... I'm not sure that can be done easily, depending on what you really want. You may be able to do something with the launch mode activity parameter in the manifest:
http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
And then have your activity respond (with onNewIntent() most likely) and "reset" itself programmatically. Possibly with something like this:
Android restart my activity
You mean re-start Activity A? While the most common approach is just to re-launch a new Intent with your same class I think it uses way too memory. I'd rather create an "init" method which should be called from the onCreate AND when you want to re-launch your activity. Example:
public void onCreate(Bundle si){
// Call super and set your layout...
init();
}
/**
* This method should be called whenever you want to restart your activity. The
* biggest advantage is you already have your layout (setContentView() method)
*/
private void relaunchActivityA(){
// Clean or save anything you need to clean or save
init();
}
private void init(){
// Init your variables, threads, and so on
}
If you wrote 'finish that and fresh start Activity A' instead of 'Activity B', then right after your startActivity() -on activity A- call 'finish'. Example:
// This is inside Activity A
Intent i = new Intent(this, ActivityB.class);
startActivity();
finish(); // This will be called right after 'Activity B' finishes
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:
remove the LAUNCHER category as defined in my AndroidManifest.xml
create a custom Application class that the app uses
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));
}
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);
}
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.
My application starts with a welcome screen Activity, but that screen has an option to skip that screen altogether in future launches.
What's the proper Android way to do this? Initially, I just automatically detected the skipWelcome preference and switched to the 2nd activity from Welcome. But this had the effect of allowing the user to hit the back button to the welcome screen we promised never to show again.
Right now, in the Welcome activity, I read the preference and call finish() on the current activity:
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
boolean skipWelcome = preferences.getBoolean("skipWelcome", false);
if (skipWelcome) {
this.finish();
}
And then I implement onDestroy to move on to the next Activity:
#Override
public void onDestroy() {
super.onDestroy();
startActivity(new Intent(Welcome.this, StartFoo.class));
}
But this makes for some weird visual transitions. I'm starting to think that I need a base Activity that pops open Welcome only if proper, and then goes to StartFoo.
I can't comment on Mayra's answer or I would (not enough rep), but that's the correct approach.
Hidden in the Android documentation is this important phrase for Activity.startActivityForResult(),
"As a special case, if you call
startActivityForResult() with a
requestCode >= 0 during the initial
onCreate(Bundle
savedInstanceState)/onResume() of your
activity, then your window will not be
displayed until a result is returned
back from the started activity. This
is to avoid visible flickering when
redirecting to another activity."
Another important note is that this call does not block and execution continues, so you need to stop execution of the onCreate by returning
if (skipWelcome) {
// Create intent
// Launch intent with startActivityForResult()
return;
}
The final piece is to call finish immediately in the welcome activity's onActivityResult as Mayra says.
There are a few solutions to this.
Did you try just launching the activity and finishing? I vauguely remember that working, but I could be wrong.
More correctly, in if(skipWelcome) you can start the new activity for result, then when onActivityResult is called, immidiately finish the welcome activity.
Or, you can have your launcher activity not have a view (don't set content), and launch either the welcome activity or StartFoo.