Android raise Notification when app goes to background (not single activity) - android

I have an Android app made of 3 activities A, B and C:
A is the application itself (a regular Activity)
B is the settings screen (made with PreferenceActivity)
C is the about screen (a regular Activity)
The relationship between the activities is as follows:
A is the main activity
B's parent is A
C's parent is B
Activity A raises a notification when going to background, this is accomplished by calling NotificationManager's notify() inside A's onStop() method.
When the user launches the app it starts from activity A, then if the user presses the home button the notification will be raised as soon as the home screen is shown. Clicking on the notification will get the user back to the app.
Everything seems to work but now there's a behaviour I tend not to like:
When the user launches the app and then goes to settings (therefore showing activity A and then B) the notification is also raised (because A has gone to background in order to show B).
This is not desired: The notification should be raised only when the application goes to background regardless of the activity the user was looking at.
How to implement this proper behaviour?
Thanks in advance,
Marco

just create a boolean flag shouldNotify and set it to false when you are opening one of your other Activities. Without your code I can't tell you exactly how to implement it but here is an example to get the idea accross:
private boolean shouldNotify = true;
#Override
public void onStart(){
super.onStart();
shouldNotify = true;
}
#Override
public void onStop(){
super.onStop();
if(shouldNotify){
sendNotification();
}
}
// Where you need to put these next snippets depends on how you've made your Activity
/*
* Launching settings activity
*/
shouldNotify = false;
Intent settingsIntent = new Intent(this, YourSettingsActivity.class);
startActivity(settingsIntent);

You could set a boolean flag which is checked before raising the notification and set it to "false" before startig Activity B.
Of course this way you would have to do the same in Activity B and C for them to raise the notification, too.
Or, as hinted to before you could implement an own application class and fetch the callback there.

Related

Make App Launch Activity not be visible in application manage after back is pressed

Basicly, i have 3 activities in my app. call them A,B and Login, A and B shows the user very sensitive data. a legit flow has the form of launch->Login->A->B->A->B...->A->quit what i really want is that if for some reason the app got to the background ( by pressing back or home or whatever ) while it was still on A, or on B, then no metter what way the app relaunches ( or traced in some way including by the long home press menu ) it would not show A or B content. he can see either the login page content, or nothing at all.
noHistory is almost what i was looking for, but isnt a good solution since i want to allow intuative navigation from A to B and back to A. so how is it done?
Check out the "clearTaskOnLaunch" Activity attribute.
When the value is "true", every time users start the task again, they
are brought to its root activity regardless of what they were last
doing in the task and regardless of whether they used the Back or Home
button to leave it.
try the following pseudo:
public A extends Activity
{
boolean just_launched = true;
void onPause()
{
just_launched = false;
}
void onResume()
{
if (!just_launched)
finish();
}
}

App is not being restored when launched from Home

I am trying to control my stop/restart behavior according to the Android Guidelines but it's getting a bit tricky. I want my app to restore state after being minimized and tapping the launcher icon.
The current behaviour makes so I can HOME out of the app, and when the user comes back using the long press list everything behaves as expected. Now, trying to return tapping the app icon starts the default activity, it doesn't take onRestoreInstanceState into account, and while keeping the old task affinities open on their back stack.
The activities have onCreate, onResume, onSavedInstanceState overridden, calling their super, and are of type SingleInstance.
During one of my app development, I had the similar issue where app have single activity and need to save some state values (usually string, Boolean) onpause. I will give you idea how i handle it, and I hope it will useful to you also.
protected void onPause() {
super.onPause();
saveState();
}
protected void onResume() {
super.onResume();
retrieveState();
}
donot forget focus change ...
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus) {
retrieveState();
}
else { saveState(); }
}
Now the save and retrieve data
public void saveState()
{
SharedPreferences settings = getSharedPreferences(WEBSTATE, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString(CURRENT_URL_STATE, "some url");
editor.putInt(FILECOUNT, 10);
/* any other content... */
editor.commit();
}
public void retrieveState()
{
SharedPreferences settings = getSharedPreferences(WEBSTATE, 0);
String current_url = settings.getString(CURRENT_URL_STATE, "");
int count = settings.getInt((FILECOUNT, 0);
/*use these value as per requier.. */
}
The current behaviour makes so I can HOME out of the app, and when the
user comes back using the long press list everything behaves as
expected. Now, trying to return tapping the app icon starts the
default activity, it doesn't take onRestoreInstanceState into account,
and while keeping the old task affinities open on their back stack.
Let's say you got 2 activities: A and B. Activity A is your entry point, so when you tap on app icon (which in fact is incorrect statement as this is activity icon, NOT the app icon) you launch activity A. Now you got to activity B and press HOME. When you now open list of recents, you will see activity B, and will be able to get back to it. But when you tap your "app icon" on launcher screen, you will enter activity A. And this is normal and correct behavior. Also note savedInstanceState is not overall state of your application as you most likely think.
Also note, that your Activity class can be instantiated multiple times, which depending on your application architecture can, also lead to incorrect navigation behaviour. You can try to control this by using android:launchMode in your Manifest file (you will find android documentation here).
Finally, if possible, consider reworking your application to use Fragments instead of multiple activities - that would simplify controling application flow.
Not sure if this is what you want to do, But i had a similar problem where i wanted a single base activity to return to, And i couldn't get the desired result from SingleInstance, I defined a new Activity which was the main launched :
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
And from that activity i launched my desired Activity with the desired FLAG clear-top, and finished the main launched activity.

how to use onResume activity in android

I am trying to build an application in which I am applying password on application. when the user left the application and open again then I will ask for the password. for example application is running , the user clicks the home button means left the application then he open it again the the application will ask for the password.
I am creating a password dialog in onResume() method of activity. but the problem is that if the user goes to the next screen and comes back to that screen then also onResume() will execute and will ask for the password. but I don't want this. I want password alert should occur only if he left the application and come again. please tell me any solution where should I write that code.
Give it a try.
Suppose u have A,B activity, create a static variable in A as loggedIn=false;
now suppose u started B from A, on B onbackpress method always make loggedIn=true;
In activity A's on resume method check
if(!loggedIn){
showLogin dialog
}
then assign true again
loggedIn=true;
now if user press home button loggedIn flag will be false and when resumes application the login dialog will be called.
You can create an activity to handle the Authentication process and lets call it (A).
and let your current activities be (B) and (C).
So, this is how it goes:
1- activity (A) is the launcher.
2- add android:noHistory="true" to the <activity> tag of activity (A) in the manifest.xml
3- from (A) you can navigate to (B) then to (C).
4- from (C) you can navigate back to (B) but you'll not be able to navigate back to (A).
You can set variable when home key is pressed
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_HOME)
{
fromHome = true;
}
return false;
};
and set variable false when you navigating from this activity
fromHome = false;
and check flag in OnResume()
Assuming you have two activities a(displaying dialog) and b.When you navigate from one activity a to another activity b. Activity a goes to background. activity b is in foreground. both are put to activity backstack. back stack works like LIFO (Last in first out). When you click back button. activity b is pushed from back stack and activity a is displayed. When activity is paused it has to resume. When you activity is stopped onStart() is called and in succesion onResume() is called. So if you calling dialog in onResume() it iwll get displayed.
Have look at the below links.
http://developer.android.com/training/basics/activity-lifecycle/index.html.
http://developer.android.com/guide/components/tasks-and-back-stack.html.
Note Quoted from the above link: Multiple tasks can be held in the background at once. However, if the user is running many background tasks at the same time, the system might begin destroying background activities in order to recover memory, causing the activity states to be lost. See the following section about Activity state.
Edit
You must implement the onCreate() method to perform basic application startup logic that should happen only once for the entire life of the activity. So display dialog in onCreate() not onResume(). Unless activity is destroyed it is not created again.
It would seem to me that what you are actually trying to keep track of is number of "Started" Activities in your Application: #(Started activities) > 0 would then mean that your application hasn't been put to the background, because if the user presses Home, ALL your App's Activities are bound to have onStop() called.
In order to keep track of the number of "Started" Activities you could introduce a singleton like so:
public class LifecycleTracker {
private LifecycleTracker mInstance;
private int mNrOfStarted;
private LifecycleTracker() {
mNrOfStarted = 0;
}
public static LifecycleTracker getInstance() {
if (mInstance == null) {
mInstance = new LifecycleTracker();
}
return mInstance;
}
public void incrementStarted() {
mNrOfStarted++;
}
public void decrementStarted() {
mNrOfStarted--;
}
public boolean fromBackground() {
return mNrOfStarted == 0;
}
}
Then, in all your Activity's onStart() methods you should first check if you are coming from the background:
if (LifecycleTracker.getInstance().fromBackground()) {
//start authentication
//don't forget to increment after authentication as well!
} else {
LifecycleTracker.getInstance().incrementStarted();
}
And in all your Activity's onStop() methods you should decrement:
LifecycleTracker.getInstance().decrementStarted();

Android App close and reopen start at beginning again

I have created a simple app for android, that uses buttons to navigate different activities the app starts at page 1, you click on page 2 or 3 button etc and that starts the required activity, simple.
What im having problems with (more of annoyance than problem) when you click HOME or come out of the app, because android doesn't kill the app straight away it is keeping the page you are on remembered and is opening the app at activity 2 or 3 for example. I want the app when closed to go back to the beginning of the app again and open at 1, i can go back to 1 by clicking back but this is really not what i wanted.
I hope someone can read this and understand, simplest solution possible please
What you need to do is use the Activity lifecycle to your advantage. When a screen is hidden for any reason, its onPause method gets called. When it's displayed again, onResume gets called. However, onResume is called even the first time a new Activity is displayed. Another problem is that onPause is called when transitioning between Activities.
So you ultimately want to "restart" the app when the last Activity's onPause and onResume are called in succession. Try this class, and have all of your Activity's extend this instead of Activity.
public abstract class BaseActivity extends Activity {
private static BaseActivity lastPausedActivity = null;
#Override
protected void onPause() {
super.onPause();
lastPausedActivity = this;
}
#Override
protected void onResume() {
super.onResume();
if(this == lastPausedActivity) {
lastPausedActivity = null;
Intent intent = new Intent(this, FirstActivity.class);
intent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP );
startActivity( intent );
}
}
}
I haven't tested this code, so it may need a few tweaks, but the logic should be sound.

Start root activity if no other activity live for this android app when press back key

I have a message notification, when user select the notificaton, a message display activity will show.
When user read the message and press back key to close the activity, I want to check if the previous activity is the same app's, if so, just go ahead, if not, I want to start the home activity for this app.
How can I do that?
How about this: Have the notification launch the Home Activity in a state that immediately has the Home Activity launch the MessageDisplayActivity. That is: (1) The intent that the notification sends should target the HomeActivity and include an extra flag identifying the Intent as being from the notification. (2) The HomeActivity, in onCreate(), upon finding that flag then simply launches the MesssageDisplayActivity.
Thus the HomeActivity will exist for a brief moment of time, but probably not long enough to be visible. It will then remain upon the back stack so that the back key will bring you there.
You should consider changing the launch mode of your Activity, so that you never have this problem - using singleTask or singleInstance should make this Activity always be the only one open for your app.
Have Intents within your app that call the message display activity (MDA) pass a boolean value of "true" that's extracted and stored in a field in the MDA. Have the field set by default to "false." Thus, if the MDA is called from an activity within your app, the field will have a boolean value of "true," if it's called from anywhere else (such as a notification), it will be set to false.
Override public void onBackPressed() in the MDA as follows:
public void onBackPressed() {
if (wasCalledFromYourApp == true) {
super.onBackPressed();
} else {
//[code that launches your app's home activity here]
}
}
(This is assuming the notification will only be created by one app).

Categories

Resources