I am using PendingIntent to take user from push notifications to Activity B i,e when user clicks on notification it will go to screen B.
I want it to be screen B only when application is loaded and running, else it should go to screen A. I have implemented this as well.
Now, there is scenario, wherein I have received the notifications, hence the intent is set to Screen B, but I haven't clicked it. If I kill the application process using DDMS or if the android kills the application before I click on notification and then I click it, it tries to load activity B which is not what I want in this case. I would like to load activity A in this case which is first sceen of the app.
Please, suggest what to do !
It sounds like you're deciding whether to launch activity A or B at the time you post the notification, which, as you've discovered, will not work: once you submit the notification to the Notification Manager, you can't make changes to it.
The way to do this is to always launch the same activity, but have that activity potentially redirect the user to a different activity based on whatever criteria you want. For example, you could launch activity B, which then bounces the user immediately to A if the app is not already in the foreground. (You could also do this with a third activity whose job is simply to route the user around, or with a service, or with a broadcast.)
Now the decision about where to send the user is made at the time the user taps on the notification, rather than at the time the notification is posted.
Related
Every browser stores history of web pages we visit, I am curious if mobile apps work similarly, what is the mechanism.
What happens when we press the back button, how does the app know which page to open up?
What you are calling "pages" is actually termed as "activities" in android. To answer your question, every android app maintains it's own Backstack to keep track of the visited activities.
According to the documentation,
The activities are arranged in a stack—the back stack)—in the order in which each activity is opened. For example, an email app might have one activity to show a list of new messages. When the user selects a message, a new activity opens to view that message. This new activity is added to the back stack. If the user presses the Back button, that new activity is finished and popped off the stack. The following video provides a good overview of how the back stack works.
Clearing an activity stack via Intent is well documented with questions like this.
However this solution assumes that you are moving from one activity to another. Is there a way to clear this stack programmatically without having to start a new activity using an Intent?
To put this question in context:
My app has a database that synchronizes with a master online database. However the app needs to be available offline, so it has a completely replicated database stored locally in SQLite. I have an activity called FullSyncActivity which basically has a button called Start Sync. When the button is pressed, the sync starts (clears existing data and re-downloads from the server) and once the sync is complete, a new activity starts again.
The problem I have is that the user might navigate to the FullSyncActivity without fully understanding it's purpose - hence why I do not want to start the sync process when the activity opens (a Start Sync button is required). However, I cannot clear the activity stack when the activity is started (using an intent), because if the user cancels without pressing the Start Sync button, then they will have nowhere to return to. Ideally I'd like to clear the activity stack once the user presses the button. Is this possible?
I would do this by using a broadcast Intent. Have each activity register a receiver for a specific broadcast Intent. When the user clicks the Start Sync button, it should broadcast this Intent. When the receiver gets the Intent, it just calls finish(). In this way you can ensure that all activities end themselves when you send the broadcast Intent.
I'm building an Android app that handles incoming events.
When I receive 1 such event, if my app is in the foreground, I immediately generate an AlertDialog that requires the user's attention.
However, when the app is in the background, the user does not see this, even though the AlertDialog has already been generated. If I manually go back to my app, I see the AlertDialog and I'm able to click OK or cancel.
I tried generating a notification dialog that appears when my app is in the background. This works, and I put the PendingIntent as MainActivity. When I tap on the notification, it brings me back to my app. However, the AlertDialog isn't there anymore.
Comparing the logcats of tapping on the notification vs manually going back to my app, I notice several differences.
When I manually go back to my app, I see MainActivity is resumed immediately. However, when I tap on the notification, it first goes back to the constructor of the class that generated the notification, a few other classes/fragments, before finally resuming MainActivity.
Does anyone know why this might be the case?
Thanks.
The default behaviour of a foreground notification is to re-launch the activity. Try setting your intent flag for the PendingIntent to use this:
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
And that will then have the same behaviour as if you navigated to the activity through your app.
From docs:
If set, the activity will not be launched if it is already running at the top of the history stack.
it seems that,you are is creating new instance of app when resuming from notification
so,add this in manifest,it might help:
android:launchMode="singleInstance"
in other case it resumes hence dialog going to be persisted.
Background
Let's take the next sceneraio:
the user uses an app X which has multiple activities (like the gmail app).
after navigating the app X a bit, he goes to your app.
in your app, you need to start this X app using an intent, to go to a specific activity within it.
now the user goes to this specific activity on the app X.
the user presses the back button, hoping to go back to your app instead of staying on the app X.
another similar scenario:
the user navigates on your app between activities.
your app went to the background (using the home button, for example).
your app shows a notification that once clicked, it will open a specific activity of your app.
the user clicks on the notification and goes to the specific activity of your app.
the user presses the back button, hoping to return to the app that was shown before clicking on the notification, instead of going to the previous activity on your app that was shown the last time it left it.
It seems that the last step on both scenarios isn't the default behavior.
This is why I've searched what is the best combination of flags for this purpose.
The problem
It seems that the only flag that can achieve the behavior i've described is Intent.FLAG_ACTIVITY_MULTIPLE_TASK (together with Intent.FLAG_ACTIVITY_NEW_TASK).
According to the android API, however, this flag isn't recommended for normal use:
Do not use this flag unless you are implementing your own top-level
application launcher.
...
Because the default system does not include
graphical task management, you should not use this flag unless you
provide some way for a user to return back to the tasks you have
launched.
This information seems as confusing as the rest of the descriptions about intents.
There are other intents flags that I've seen, like Intent.FLAG_ACTIVITY_CLEAR_TASK that achieve a similar result, but they have weird behaviors and/or they use high API
The question
Is it safe to use this flag? Are there any good alternatives to it?
What is the danger of using this flag and what is the meaning of the description on the API of using it?
In your first scenario, if your app needs to start an activity of another app, it can just start this activity within the same task as your application. There is no reason to use any special Intent flags for this (you don't need FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_MULTIPLE_TASK). In step 5 of your scenario, the user will return to your application (because BACK just takes him to the previous activity in the current task). This is the standard, default behaviour.
In your second scenario, my first response is "that isn't the standard behaviour". That means that users probably won't expect to be able to go back to the task that they were doing prior to clicking on the notification. However, if you really want to implement this, then I would suggest that you create a special Activity that is launched from the notification and this special Activity should have a different taskAffinity than the rest of the Activities in your application. In this case, when the special Activity is launched from the notification, it will not bring your application's task to the foreground. It will just create a new task containing just the special Activity. When the special Activity is showing, the user can press the BACK key and this will return him to the task that he was working on prior to clicking on your notification.
In general you should NOT use FLAG_ACTIVITY_MULTIPLE_TASK. The main reason is that if you have several tasks containing your application (or parts of it), it is pretty much impossible for the user to return to a specific one. There is no way to provide different launch icons or different application names (for the different tasks)(, so that the user will see multiple tasks in the "recent tasks" list, but will not be able to tell which one is which. You will have a hard time cleaning up what you are doing and you will just make more problems than you can deal with. There are about a million side effects of using this flag and for general applicaitons there is just no need to do it.
I am currently developing an android app which uses the android web browser and notifications.
What I want to be able to do is the user clicks on an item which loads the android web browser and makes a notification in the notification bar as well.
The user should be on the browser when they go the notification, so when the user is on the browser and they click on the notification I want the notification to perform its task but not redisplay the app activity instead just return to where the user was on the browser.
I've tried setting the different flags on the activity but none of them seem to make any difference.
Thanks for any help you can provide.
According to the following quote from the Android documentation, it sounds like there isn't a way to do some kind of background task without starting an activity when a user clicks a notification. Although you may want to look into sending an Intent to a Service. I've have not tried that before so I can't say whether it works or not.
A notification always starts an
activity as a new task (that is, it
puts FLAG_ACTIVITY_NEW_TASK in the
intent it passes to startActivity())
The documentation also suggests you could have a dedicated activity that could perform the copy paste, and then the user could simply press back to get back to the browser:
For example, when the user receives a
Calendar notification, choosing that
notification starts a special activity
that displays a list of upcoming
calendar events — this view is
available only from the notification,
not through the Calendar's own user
interface. After viewing this upcoming
event, to ensure that the user
pressing the BACK key will return to
the activity the user was in when they
picked the notification, you would
make sure this dedicated activity does
not have the same task affinity as the
Calendar or any other activity. (You
do this by setting task affinity to
the empty string, which means it has
no affinity to anything.)
To get round this as I did not want to have a service running in the background to perform this simple task what I have done is called the method at the end of the activity that the notification calls.
I call moveTaskToBack(true); which places the task into the background. As if the user presses the home button.