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)
Related
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)
I have an activity. The launch mode is singleTask, and I implement onNewIntent. When I send an intent to launch this activity while the activity is open (with flags NEW_TASK and RESET_TASK_IF_NEEDED), the screen flashes before showing me the same activity.
Why could this be happening? I thought singleTask should be enough to ensure that new intents are delivered to onNewIntent, rather than the system spinning up a new task or anything for my activity. The flashing goes away when I do either of the following things:
change the launch mode to singleTop;
add the flag Intent.FLAG_ACTIVITY_CLEAR_TOP to the launch intent.
I'm curious to know what's going on and what, if anything, I could do to overcome the flashing (I'd really prefer not to change the launch mode or launch intent flags, if at all possible). Basically, is there any good reason why this should not work?
Note that I do get onNewIntent, even though the screen flashes.
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
I've searched and searched and searched for this!
So I've got an app widget and it has a configuration activity that I can open when pressing a button on the app. The scenario is:
Had the app opened.
Closed the app with the home button.
Selected to add my widget
I have configured the widget.
Placed on my home screen
Then open the configuration activity again with the button on the widget.
Cancel the new config by pressing back will put me back into the app.
When pressing back I want to just return home.
Basically what I'm asking is. How do I start the configuration activity in it's own task/stack?
I've looked into intent filters but I'm just not quite sure, or maybe it's something to do with the package it's in, or maybe it's just not possible!
I suppose it may have something to do with the intent I use to launch the config activity
Intent configIntent = new Intent(this, Configuration.class);
configIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
remoteView.setOnClickPendingIntent(R.id.config, PendingIntent.getActivity(this, 0, configIntent, PendingIntent.FLAG_UPDATE_CURRENT));
Perhaps because I launch it with 'this' as the context, it will always start in my applications stack...
but the pending intent api is:
PendingIntent API 1
"Note that the activity will be started outside of the context of an existing activity"
So yeah I'll stop talking now as I just end up going in circles!
EDIT
So tried android:launchMode="singleInstance" in the manifest like was stated. This worked however it stops the 'startActivityForResult' behaviour working correctly. (which is the whole reason for a config activity) Get the error:
WARN/ActivityManager(59): Activity is launching as a new task, so cancelling activity result.
So still haven't found a solution.
Ok sorted it :-) needed:
android:taskAffinity=""
in the manifest, setting the task affinity to an empty string allows for the activity to start in it's own stack, as it is not 'affiliated' with the rest of the application.
UPDATE
I have changed the task affinity to:
android:taskAffinity="com.my.package.alternative.task"
as each time I launched the activity it was showing up multiple times in the 'history'. So it now starts in it's own stack but is shared with other instances of the same activity.
Also need to add the Flag Intent.FLAG_ACTIVITY_NO_HISTORY to your intent :-) this stops your getting your application multiple time's in the history when you 'press and hold' the home button.
UPDATE
I've noticed FLAG_ACTIVITY_NO_HISTORY wasn't doing what I wanted, I've removed it and added:
android:excludeFromRecents="true"
into the activity tag in the manifest as well. The activity now behaves like I want :-)
Got this answer from the following link trail:
Tasks & Back Stack |
Managing Tasks |
Affiliation Tag
Try to put android:launchMode="singleInstance" for an activity of the app in AndroidManifest.xml
I guess that Android won't let people to do this, because they think they have perfect handle for the task/applications. However, I really need to do this in my case.
I have an activity A acting as the entry point of my application. In that activity, it reads the preference and decided which activity to start, say B or C. After that, it finishes itself. So, activity A never appears to the users.
My application stores things on sdcard, and reads from it constantly. So, when the sdcard is unmounted, I need to display a message to the user that the sdcard is unavailable, instead of opening B or C. I set a check in A to display that message when sdcard is unavilable. When that message is displayed, A will not try to start B or C.
Things works perfectly if user only enter my application from application launcher. However, I found that user can also enter my application by long pressing home and choose it from the recent application list, if he has opened it recently. When user does that, it skips A and goes directly to B or C. I don't have the check in both of them, so exception is thrown while I am trying to access sdcard, and force close dialog pops up.
I can simply move my check to both B and C to fix this problem. But in the future, the number of activities started from A will increase. If there are 6 of them, I'll need to copy this check to 6 places. Needless to say, this looks very ugly, and is a maintenance nightmare.
So, the best fix should be removing my application from recent application list when the sdcard is uunmounted. However, I can't find how to do this. Even killing the process or use ActivityManager.restartPackage, it still appears in the list. Can anyone tell me how to remove it from the list?
try
<activity android:name=".MainActivity"
android:excludeFromRecents="true" ...
in your AndroidManifest.xml's activity declaration.
Other attributes can help your activity isolate from other activities in the same package.
<activity
android:name=".aActivity"
android:excludeFromRecents="true"
android:taskAffinity=""
android:launchMode="singleInstance">
just add android:excludeFromRecents="true" in your activity's tag in the manifest file..its easy
You need to set below code in Launcher Activity in AndroidManifest.xml :
<activity>
...
android:excludeFromRecents="true"
...
</activity>
or start this activity from
intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
and also in AndroidManifest.xml
<activity>
...
android:label=""
...
</activity>
Setting label as empty will let this activity NOT be shown in Recent App list.
I would not recommend to do so but I would try the following options:
Option 1:
On B and C add:
protected void onPause() {
finish();
}
Option 2:
Add to B and C the following in the AndroidManifest:
android:noHistory= "true"
Removing your application from the recent apps list is probably not possible, and definitely not the best solution. That will just confuse the user who expects all apps to behave similarly.
Regardless, I don't think it will solve your problem. If the user hits home while on Activity B, then selects your app from the home page, it will start Activiy B again.
There are a number of ways to solve the real problem. One easy one might be to create a base Activity that performs the SD card check, and have all of your activities extend from it. That way the check is only in one place.
OK, I know for a fact that it can be done in 2.3.4. The app Toddler Lock when opened clears the recent app list so that when you "Lock" your phone if you long press home key the list is blank. Unfortunately I have not found how to do it. So for anyone who is looking and reading postf that say it is not possible don't give up. I sure heck am not.
if you wanna exit Application on Button click use this code :
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
To kill the complete app and remove it from Runningapp list kill the app through its pid(its nasty)... use this lines before above code.
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
try this,
it will finish all activities and remove app from recents
private fun killCurrentApp() {
val am = this.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager?
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val appTasks = am!!.getAppTasks()
if (appTasks.size > 0) {
val appTask = appTasks.get(0)
appTask.finishAndRemoveTask()
}
}
}