Starting multiple instances of the same Activity from Service - android

I want to start multiple instance of the same Activity class from a Service. The reason I'm doing this, is because I have a Service that runs a "scan" daily, and if it finds any malfunctions it should display a popup for each malfunction.
The Activity that I'm starting is more like a Dialog, has a Dialog theme to display info about the malfunction.
Manfiest:
<activity
android:name=".ui.dialogs.MalfunctionActivity"
android:theme="#style/MyDialog"
android:launchMode="standard">
Intent to start the activity from Service:
Intent displayMalf=new Intent(this, MalfunctionActivity.class);
displayMalf.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(displayMalf);
PROBLEM: to start the Activity from a Service I need the FLAG_ACTIVITY_NEW_TASK which somehow cancels the launchMode="standard" from the manifest, and gives me just one Activity even if I try to start multiple diffrent instances.
Is there anyway in which I can achieve this?

It was so simple. There is the 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.
Was exactly what I need. Thanks and sorry for answering on my question. It is not a habit. :)

Service will take the flag FLAG_ACTIVITY_NEW_TASK to start the activity but here you can try like this:
Set the instance of the handler of the activity of which you want multiple instances, in the service.
When you want the new instance of the activity use handler.sendMessage(msg) and on receiving this msg in your activity, start this activity again.

I guess your app works in the background and will display the popups even if the app is not in the foreground at the moment, right?
Otherwise I would use normal popup's (AlertViews) instead of starting new activities all the time.
If the app works in the background, you could tell the user with the first popup that your app has found one or more malfunctions and that he should activate the app for more details

Related

What happens when you click on an application's launch icon?

 What happens when you click on an app's launch icon?
Is a new intent always sent, or is the result sometimes the same as resuming a task from recent tasks?
If an intent is sent, when does it get sent to the onCreate() method of a new activity instance and when does it get routed through onNewIntent() of an existing activity?
Let's suppose the intent gets routed through onNewIntent() of an existing activity in the task. Which activity does it get sent to? The one nearest the top or the one nearest the root? Will it always get sent to an instance of the application's launch activity or can it sometimes get sent to an activity with the same affinity as the root? Can it ever get sent to an activity which does not share the same affinity as the root?
Finally, how is this all affected by the various launch modes (standard, single top, single instance, single task) of the activities in the task?
If there is anyone out there who understands all this, please help me!
What happens when you click on an app's launch icon?
Launcher apps calls startActivity with an intent [action = Intent.ACTION_MAIN, category = Intent.CATEGORY_LAUNCHER and flag = Intent.FLAG_ACTIVITY_NEW_TASK].
Regarding Intent.FLAG_ACTIVITY_NEW_TASK, from docs:
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.
onNewIntent basics:
onNewIntent is delivered only when activity has set either singleTask, singleInstance launch modes. It is also delivered if activity has set singleTop launch mode or the intent to start the activity has set the flag FLAG_ACTIVITY_SINGLE_TOP and the activity instance is already at the top of the target task. It means an attempt was made to launch a new instance of activity, instead the existing instance itself need to handle the intent.
Here is the response to your queries:
Is a new intent always sent, or is the result sometimes the same as
resuming a task from recent tasks?
If the task is already running, it is brought to foreground. In case FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET flag was used to launch a activity and latter the task is brought to foreground, then the activity is killed. From docs:
This is useful for cases where you have a logical break in your
application. For example, an e-mail application may have a command to
view an attachment, which launches an image view activity to display
it. This activity should be part of the e-mail application's task,
since it is a part of the task the user is involved in. However, if
the user leaves that task, and later selects the e-mail app from home,
we may like them to return to the conversation they were viewing, not
the picture attachment, since that is confusing. By setting this flag
when launching the image viewer, that viewer and any activities it
starts will be removed the next time the user returns to mail.
-
If an intent is sent, when does it get sent to the onCreate() method
of a new activity instance and when does it get routed through
onNewIntent() of an existing activity?
onCreate is called while creating a new instance of activity. onNewIntent is called if already an activity instance exists and no new instance need to be created, as in case of singleInstance, singleTask and conditionally singleTop (as described above).
Let's suppose the intent gets routed through onNewIntent() of an
existing activity in the task. Which activity does it get sent to? The
one nearest the top or the one nearest the root? Will it always get
sent to an instance of the application's launch activity or can it
sometimes get sent to an activity with the same affinity as the root?
Can it ever get sent to an activity which does not share the same
affinity as the root?
In case of singleTask and singleInstance it has to be root of the task. In case of singleTop it has to be top activity of the task.
Finally, how is this all affected by the various launch modes
(standard, single top, single instance, single task) of the activities
in the task?
I hope the explanation provided till now, answers it.
Update 1:
Here is the Launcher code which adds the flags to intent:
void processShortcut(Intent intent) {
....
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
....
}
void startActivitySafely(Intent intent) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
...
startActivity(intent);
}
Your best bet is to read through the Developer docs here: http://developer.android.com/training/basics/activity-lifecycle/index.html
There is a flow chart in the first lesson(http://developer.android.com/images/training/basics/basic-lifecycle.png) which provides an excellent graphical representation of the Android activity life-cycle.

Exclude current activity from Recent Tasks

My app, running in background, at some point displays activity to purposefully interrupt user's flow. My activity starts a new task, which appears in "Recent Tasks" lists while being in foreground. Is there any way it could be prevented? Setting android:excludeFromRecents does not work - activity is not presented anymore in "Recent Tasks" only after is has been paused.
Manifest looks like:
<activity
android:name="com.example.recenttasks.MainActivity"
android:excludeFromRecents="true">
</activity>
and activity is started this way:
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
The key thing you mentioned is
appears in "Recent Tasks" lists while being in foreground
I think you can't change that behavior. I just tested on my app and the same thing happens. If I press the "recent tasks" button while having my activity in the foreground, it appears listed there. The moment I move out of it to another activity or to my phone's main screen, the activity is not listed anymore.
I also tested this on the built-in DeskClock app that comes with recent Android versions and the same behavior is present there when a new alarm is triggered. Note that the AlarmAlertFullscreen activity of that app has the same parameters you mentioned in your question.
I'm not sure you can circumvent this or why you would need to in the first place since the activity is not listed anymore once it loses the focus.
you are defined it in manifest that is enough but it is not coming..
ok..try add this flag also to your Intnet and start the Activity..
intnet.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Should the user be able to return to it? (Meaning if it shows and user clicks recents, have they lost their chance to see the hidden activity or should it still be there?)
If they cannot return to it anyway then the best action would be to finish() the activity onPause(). This will mean that as long as you have used android:excludeFromRecents and android:noHistory="true", there will be no item in recents.
If however you do wish to return to the 'interruption' activity (but do not want a recents entry) you could consider still finishing the activity onPause - but also recording a preference flag (something like IS_INTERSTITIAL). Your other activities can then check this preference in onResume and, if it is true, send an Intent to restart the Interstitial instead - To the user it will just appear they are resuming the app in the same state as they left it (interstitial)
Edit: If the screen needs to stay (rather than be re-instantiated) it may be possible to use a DialogFragment, although then you must worry about configuration changes. There is one hack you could try (explained in this answer) -
Set your label empty By using android:label="" your recent task is excluded. however this is a definite hack which may produce inconsistent results (as I haven't tested it to be sure)

Create new intent in background

I am looking for a way to launch another app from within my app but so that the focus is not changed from my app to the app launched.
I.e currently I have the new app launched via a intent, however when this is carried out the new app is launched and becomes the app in view, I need it to be kept in the background with my app still in view.
The reason for this?
I am developing an application for internal use that will act like a lock-screen to the device so although things must happen in the background the 'lock-screen' must always be on top.
I have done some research into intents and launching other apps but can not find anything about what I need.
Hope you can help thank you!
Currently the terminal is called like this:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("jackpal.androidterm", "jackpal.androidterm.RemoteInterface"));
intent.setAction("jackpal.androidterm.RUN_SCRIPT");
intent.putExtra("jackpal.androidterm.iInitialCommand", cmdString);
The reason it needs to be running in the background is so that the app can run commands in terminal without the user having access, but then they 'unlock' the screen they need to then be able to view the terminal and what commands are being run etc
You can not startActivity in Background.Instead start the activity and minimise the activity(in your case this activity is of different application) using moveTaskToBack(true);
In your case, put a condition based on your intent and its params and use moveTaskToBack(true); so that activity will be minimised only when your application launches.
This won't be possible, you will have to start a background Service that does the actual work and only launch the Activity you want to navigate to once your foreground Activity is finished. Depending on your architecture, you can store the Activity to call when your foreground Activity is finished and change it from the service. That way you will have your desire behaviour without having to actually call the Activity.
In addition to the answer from #Meher, in the intent for your current starting activity, you can add the flag FLAG_FROM_BACKGROUND.
With this you get rid of the "blinking" effect (the one where your activity shows for one fraction of second while it discovers wether to go to background)

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);

open every time new Activity using broadcast reciever in android

I want to open an activity using broadcast receiver. I am implement it and it works fine when activity not running in background. But if activity is running in background then it can't launch new activity it return same activity, but i want to open this activity again, means multiple instance of the activity
so, please help me how I can do this.
So you want Intent.FLAG_ACTIVITY_NEW_TASK
Refer: http://developer.android.com/reference/android/content/Intent.html
Edit:
Or perhaps, FLAG_ACTIVITY_MULTIPLE_TASK . But it's not recommended as it messes with the navigational path of user.

Categories

Resources