Android - Bring an activity to the front from application class - android

I am trying to bring an activity to the front. I found many questions similar to this but none of them actually works.
I always hold a reference to the current activity in a variable in application class. While the application is running in the background (after onPause fires), if any message arrives, I need to bring the same activity to the front and display the message. The only way I got it worked is..
Intent i = new Intent(mCurrentActivity, JoboffersActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
The issue I have got with this, is that it recreates the activity which I wanted to avoid. I tried singleInstance and singleTask both in the manifest. If I do not add FLAG_ACTIVITY_CLEAR_TOP, on back key press it takes me to the previous instance of the same activity. Even if I add sigleInstance it creates two instances of the same activity. If I do not add FLAG_ACTIVITY_NEW_TASK then it shows an error Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag

Try to add another flag FLAG_ACTIVITY_SINGLE_TOP to your intent.
According to Android documentation, combination of this 2 flags:
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
brings the current instance of Activity to the front.
http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_CLEAR_TOP

Related

Displaying a Specific Activity Without Displaying the Main Activity of the Application

I have an Intent which starts/open an activity/window that is triggered by an alarm. Everything works fine, however the Main activity/window of the Application is also open behind the first activity referenced above when triggered. Thus, when this activity is dismissed (with the help of a button), the Main window of the Application is displayed on the device. How can I open my activity without opening the Main activity of the Application? Basically, the user shound't be seeing the Main activity of the Application upon dismissing the activity triggered by the alarm. Please note that I am not explicitly calling the Main activity upon opening the specific activity mentioned above. Is this normal behaviour, or am I doing something wrong?
The specific activity is launched with the following lines:
Intent intentRead = new Intent(context, myActivity.class);
intentRead.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intentRead);
Problem
Your code starts a new Activity in a new task :
Intent intentRead = new Intent(context, myActivity.class);
intentRead.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intentRead);
The Flags make sure that the new activity gets its own task and the activity will not be launched if it is already running at the top of the history stack.
Now, suppose your MainActivity is already in the background(recent apps) and alarm is triggered which starts your myActivity. If no instance of myActivity is present then a second task is created for it. Else if an instance is present then the all activities on top of myActivity in the second task will be removed.
Solution
In your case, as you want to clear any other activities present you should use :
Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK
Intent.FLAG_ACTIVITY_CLEAR_TASK
If set in an Intent passed to Context.startActivity(), this flag will
cause any existing task that would be associated with the activity to
be cleared before the activity is started. That is, the activity
becomes the new root of an otherwise empty task, and any old
activities are finished. This can only be used in conjunction with
FLAG_ACTIVITY_NEW_TASK.
Suppose the first activity is started by your main activity, could you just finish main activity after starting the first activity. I mean like this:
startActivity(MainActivity.this, FirstActivity.class);
MainActivity.this.finish();

How to come back to First activity without its onCreate() called

I have 3 activity . Activity A ,Activity B, Activity C.
This is the flow A->B->C.
Now i want to come to activity A from C .(i.e C->A) without getting its onCreate() called of Activity A.
so far my code is:But it will call onCreate() of ActivityA.
I want to call Restart().
Intent intent=new Intent(ActivityC.this,ActivityA.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
Two cases:
If you want to keep other activities live and just want to bring A to front, just use intent flag FLAG_ACTIVITY_REORDER_TO_FRONT.
If you don't want to clear all activities and want existing instance of A at top, then use intent flags FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP.
Note : If you use only FLAG_ACTIVITY_CLEAR_TOP, then onCreate will be called.
Keep android:launchMode="singleTask" in manifest at activity declaretion
An Activity with singleTask launchMode is allowed to have only one instance in the system
If instance already exists, i will not call 'onCreate' it will call 'onNewIntent' method.
See http://androidsrc.net/android-activity-launch-mode-example/ for better understand about launch modes.
Although setting the launch mode to singleTask will work, use of that launch mode is discouraged. The documentation for launch mode indicates singleTask is "not recommended for general use".
The desired behavior can be achieved using Intent flags FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP:
Intent intent=new Intent(ActivityC.this,ActivityA.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
finish();
Activity A will not be recreated and will receive the intent via onNewIntent().
Use SingleTask launch mode for Activity A.
New intent will be delivered to existing instance.

Resume activity from broadcast receiver

I'm trying to resume an activity from within a broadcast receiver's onReceive() method as follows:
Intent i = new Intent(context, TimerSet.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
However the activity (TimerSet.class) is recreated instead of resumed. The only recommended solution I found to this problem was to use the FLAG_ACTIVITY_REORDER_TO_FRONT but I'm already using it.
Also, using Intent.FLAG_ACTIVITY_NEW_TASK doesn't fit my use case but I get the following exception when I do not provide it:
android:util.AndroidRuntimeException: Calling startActivity() from outside of an
Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you
want?
I am not sure whether this is exactly your problem or not, but I have a situation where I got a notification and I want to start my app without starting a new instance (if it's already running)
I finally figured out that these will work. The FLAG_ACTIVITY_NEW_TASK will not start a new instant if the activity has already been running. However, it will add it to the existing stack. Therefore, we can do a FLAG_ACTIVITY_CLEAR_TOP, so back will bring user to the home screen but not the previous state.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
remove FLAG_ACTIVITY_NEW_TASK flag.
also add this flag ->FLAG_ACTIVITY_CLEAR_TOP. This would prevent new activity to be created if already present.

Multiple Instances of an Activity

I am trying to show the user information on incoming-call screen, whenever there is an incoming-call. So I have a broadcast receiver listening to incoming calls, which starts the intent service, which subsequently starts an activity (with Theme Dialog).
Now, whenever there is an incoming-call, my activity dialog pops up and shows as intended.
Problem: When the activity dialog is already on the screen and incoming-call happens, there is no new activity dialog with new information. I guess that whenever there is an instance, Android does not creates the new one. So it seems like my problem is "creating multiple instances of an activity".
Please note that I am starting an activity from an intent service using FLAG_NEW_TASK.
Google Doc says :
FLAG_ACTIVITY_NEW_TASK
"When using this flag, if a task is already running for the activity
you are now starting, then a new activity will not be started;
instead, the current task will simply be brought to the front of the
screen with the state it was last in."
So, if you want to start a new fresh activity then simply not use this flag only, you should use it with FLAG_ACTIVITY_CLEAR_TASK for the desired result.
For Example:
// Sets the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TASK);
If the above solution is not what you needed, then have a look at
android:launchMode attribute, declare this attribute with the desired options (i.e. as per your need) in activity tag of manifest file.
Hope this will solve the problem.
Use flag FLAG_ACTIVITY_MULTIPLE_TASK which according to the documentation :
Used in conjunction with FLAG_ACTIVITY_NEW_TASK to disable the behavior of bringing an existing task to the foreground. When set, a new task is always started to host the Activity for the Intent, regardless of whether there is already an existing task running the same thing.
Using this flag along with FLAG_ACTIVITY_NEW_TASK will cause each activity instance to be created as a separate task and thus you can have different dialog pop ups.
Simply add following flags to your Intent .
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK);

Why does starting an activity from a widget cause my main activity to start as well?

When I start an activitiy from a widget I want the back button to go to the home screen but instead it goes to the app's main activity. After toying around I found that if I somehow close the main app activity, this problem doesn't occur. Strange.
I found a solution here that said to call finish(); in my main activity's onPause(). Obviously this is the wrong solution e.g. reorientation of the screen causes an onPause() so the will activity will die whenever the phone is rotated.
This is how I start my activity:
#Override
public void onReceive(Context context, Intent intent) {
[...]
//new Emergency().emDialog(context).show();
Intent myIntent = new Intent(context, EmergencyActivity.class);
// FLAG_ACTIVITY_NEW_TASK is needed because we're not in an activity
// already, without it we crash.
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
You can see the rest of the code at http://code.google.com/p/emergencybutton/source/browse
edit: I tried running the activity differently, but still it doesn't work correctly:
Intent myIntent = new Intent();
myIntent.setClassName("com.emergency.button", "com.emergency.button.EmergencyActivity");
Ok, so I'm not exactly sure what happened here but android:launchMode="singleInstance" in the activity in AndroidManifest.xml fixed it somehow.
<activity android:name=".EmergencyActivity"
android:launchMode="singleInstance"
#Octavian - I should have clarified that I start the activity from an onReceive in an AppWidgetProvider. I'm at the home screen, starting an activity titled B, but somehow both A and B are in the activity stack instead of just B.
http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
Although I've never used widgets, I believe that when you click the widget you are resuming an existing task. Hence, when you are in that task, you will return to the latest activity in that task (instead of Home).
See this link and choose the proper launch mode for your widget
http://developer.android.com/guide/topics/fundamentals.html#lmodes
The behavior is not strange it is just the way Android works. The activity stack just keeps track of the all the activities. Now when you start an activity A which starts another activity B then your stack looks like (B, A). If you press the back key then activity B is going to get popped off the stack and A is going to be brought to foreground again.
The right solution is to just call finish() right after firing off the Intent.
Sometimes it's not possible to use launchMode singleInstance in application for some reasons.
In this case, you should start your activity and clear activity stack. You can archive this using flags. There is an example:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Categories

Resources