In my android client program, when ever the user has updates a notification is received. When the user clicks on the notification, he is taken to a new activity where the notifications are displayed. Now the problem is while the user is viewing the updates if another notification is received and if he clicks on that notification a new activity is not being created. The previous activity is displayed. the activity is not getting refreshed.<
I suspect this is because the current activity is not finished. How should I overcome this?
Why dont you try onWindowFocusChanged (boolean hasFocus) in your code. What is happening in your case is the Activity Window is already in focussed state So nothing will happen when you click the notification bar and move to the same activity window.
onWindowFocusChanged (boolean hasFocus) will get executed each time you enter into that activity. So put your entire code into this. Even when the activity is called for first time,It will get executed. So copy ur code from public void onCreate(Bundle savedInstanceState) to
public void onWindowFocusChanged (boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
setContentView(R.layout.layout_name);
//Your code to be executed here
}
And yea you need to have Oncreate() function also so you declare that as
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
Try this. I hope it works for you
put this in the activity code in your manifest (can play with the parameter to fit better to your app).
android:launchMode="singleTop"
Try to add this attribute on your activity tag on the manifest :
android:launchMode=["multiple" | "singleTop" |
"singleTask" | "singleInstance"]
with value singleTop, it will not create an other activity but call the onNewIntent method of a potential Activity if exists.
Activity Element Documentation
Instead of finishing the current activity why should you use the onResume() method to update the ui with new notification data. Write the method to update the ui components and call it from onResume().
Related
Original question:
A button in my app starts an activity, which needs some time to prepare classes.
To let a user know this, I start a new loading activity that starts the actual activity.
This activity needs to be shown before the actual is started.
But all methods of the Android lifecycle seem to be called before the activity is shown to the user and if I start a new activity before the activity I'm currently in is shown, it won't be shown anymore.
I tried:
Starting the activity in another thread, but this does not work because the startActivity(...) seems to block the UI reload
Waiting a few milliseconds before starting the activity, but this seems dirty
Any help is appreciated! Please tell me if using a forward activity is not the right solution!
Answer for people who are searching:
Use this code to do something when the activity is already visible:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
// do something
}
}
If the activity can also turn visible shortly after your code, use Androids lifecycle methods (here probably onResume()):
#Override
protected void onResume() {
super.onResume();
// do something
}
I have 3 pages in my application. Page A,B,C. When i click next button in A page the page will navigate to B page. In that page there will be some request and response process and Progress indicator will happen. Then when i click next the page will navigate to C page. There also some request and response process and Progress indicator process will happen. Now my problem is when i click back button from page C The page is navigate to B page. But the request response process and progress indicator process is working. Here i don't want do this process when i click back button. Now i have try like this:-
#Override
protected void onStart() {
super.onStart();
Log.v(this.getClass().toString(),"onStart");
}
Here the request and response process is not working when i click back button. But the progress indicator is loading. This progress indicator is continuously rolling. How to disable all the functions. I just want to go back. Do not do any other work. Please help me to solve this issue. Sorry For the poor English..
As you can see, you add a flag Intent.FLAG_ACTIVITY_CLEAR_TOP. This flag will clear all previous activities.
Intent.FLAG_ACTIVITY_CLEAR_TOP - If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.
And also you finish the current activity, so navigating back to page B call B's onCreate method where you have those requests and process stuff. Avoid adding flag and finish() methods.
You don't want to override the onCreate() method for this usecase, why would you do that? The activity is created, and the process will run. What you want is to override the onBackPressed() method, so that you cannot exit the Activity until the process is complete.
Similarly to these: Android: Proper Way to use onBackPressed() with Toast but here you want to make a boolean that is set to false while the process is not complete, and set to true when it's done. Allow onBackPressed() to call super.onBackPressed() only when the boolean is true.
#Override
public void onBackPressed()
{
if(processesCompleted == true)
{
super.onBackPressed();
}
}
You can't disable the onCreate() method in android but you can however override it like you do with the onStart().
I suggest you take a look at the life cycles of either fragments or activities, depending on which you use.
Fragments:
http://developer.android.com/guide/components/fragments.html
Activities:
http://developer.android.com/reference/android/app/Activity.html
It is hard to understand what the problem really is without more code, but basically the code in onCreate will mostly not be called when you press the backbutton since an activity will be paused until the phone needs more resources and then destroys it. If an activity is destroyed the onCreate method will be called and there is nothing you can do to change that.
If my answer dosen't help, please provide more example code.
If all your cards have different activities, the backbutton should work perfectly. However if your activity is brought to the front, nothing will be reloaded, except the onresume. In the onresume you can perform a new loading structure or something you want to achieve.
When you don't have different activities, use the override at onBackPressed(), that will handle the backbutton.
But place some code for a better answer
You can create a new function in which you run the processes and call
it on onCreate and use a Boolean flag to make sure when you go back to
that activity and flag is checked the function is not called. Then
save the value of flag in savedPreference onPause() method and you are
done and onCreate() method load your saved preference.
Something like this
boolean flag = false;
#Override
public void onResume()
{
super.onResume();
// load savedPreferences
}
#Override
public void onPause()
{
super.onPause();
//save savedPreferences
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if(flag == false)
{
//function call
processes();
}
}
private void processes()
{
flag = true;
// do stuff here
}
I have application and when I navigate back using Intent and startActivity(), views are null, onCreate() is called and activities are re-initialized. Why is that and how to bypass it?
I navigate back to activity like that:
#Override
public void onBackPressed() {
if (this.getClass() == XXX.class) {
Intent i = new Intent(this, YYY.class);
startActivity(i); //<-- activity restarts
return;
}
}
super.onBackPressed();
}
I use ActionbarSherlock, so I have activity with ActionBar initialization and every single activity just extends it. The way I navigate back to activity is described in this activity.
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
initUIComponents();
setListeners();
resetProgress();
}
and initUI() initializes UI.
EDIT
What I mean, how can I go back to previously created activity (not the one that is called via onBackPressed) and not recreate it? I use startActivity(), but apparently it recreates the whole thing
If you want that when you press back, you want to show the previous screen, then you don't have to do it in your code. Android Runtime internally maintains the stack, and will take care of showing the last-shown-activity when you press back. No need to handle it via onBackPressed()
However, if you want something other than this default action, that is when you should use onBackPressed(). Else, just let Android handle it.
So, in your application, if Activity 1 calls Activity 2, and user presses back, then the default action would be to show Activity 1 again. Don't override the onBackPressed() method
Edit:
For a custom flow of activities, you'll have to build the logic yourself. You need to override onRestart() in Activity 1, and onStop() in Activity 3. That way, onCreate won't be called again. By your logic, I mean, flags to keep track of which activity you're in, checking those flags, and calling the desired activity from there.
Edit 2:
This previous SO question, answers what you need:
Android Activity management , which suggests setting the flag FLAG_ACTIVITY_REORDER_TO_FRONT on the intent, and then calling startActivity()
Check out Android activity stack management using Intent flags for other stack reordering options: Stack management
I have two activities but I want to apply a condition on application start, if one is true then start first activity else start second activity. Right now I am doing it by starting a third activity displaying some welcome stuff and examining the value in background..then appropriate activity gets called. I think there must be some standard way to do this. Peace.
Since you need to specify starting activity in manifest, you can always start first activity, check your condition on onCreate() and if you need to start second one - start second one and call finish() for the first activity.
Otherwise usually people use splash activity to check all the conditions at the startup (which is your current solution).
There's no need for a third Activity to check the condition.
If you simply have your MAIN/LAUNCHER Activity check on the condition as the very first thing it does in onCreate(...) (but after calling super.onCreate(...)), it can either continue or call startActivity(...) for the other Activity and immediately call finish() to self-terminate.
That way the first Activity will never be seen if the condition dictates the second Activity should be started.
Example..
public class FirstActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Don't even set the content view at this point
// we want to be invisible for the moment
// Pseudo-code check for condition
if (!runMe) {
Intent i = new Intent(this, SecondActivity.class);
startActivity(i);
finish();
}
else {
// Continue as normal
setContentView(R.layout.main);
...
}
}
}
A snippet from the Android Activities document(scroll down to the "foreground lifetime" line) says :
An activity can frequently transition in and out of the foreground—for
example, onPause() is called when the device goes to sleep or when a
dialog appears.
I don't quite understand this. Under what circumstances should this happen? Is onPause() called only if the context of the dialog in question is different from the activity on top of which the dialog is to be displayed?
EDIT: Adding code sample to illustrate my doubt in detail
Going by the above-mentioned quote from document, should my activity's onPause() method get called when the AlertDialog (or just the Dialog) in the following code gets displayed? Should I see the "onPause called" log entry when the dialog is displayed?
But I don't see that happen. And it shouldn't either, if I have understood the Android life cycle correctly! So, what's the document pointing at then?
public class LifeCycleTestActivity extends Activity {
private static final String TAG = "LifeCycleTest";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "onClick");
AlertDialog dialog = new AlertDialog.Builder(LifeCycleTestActivity.this).create();
dialog.setMessage("You Clicked on the button");
dialog.setTitle("Dialog!");
dialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
dialog.setCancelable(true);
dialog.show();
/*
Dialog dialog = new Dialog(LifeCycleTestActivity.this);
dialog.setTitle("Dialog!");
dialog.setCancelable(true);
dialog.show();
*/
}
});
}
#Override
protected void onPause() {
Log.d(TAG, "onPause() called");
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume() called");
}
}
onPause() is called when your activity is no longer at the top of the activity stack. A Dialog by itself is not an Activity, so will not replace the current Activity at the top of the stack, so will not cause anything to pause.
A dialog (lower-case) does not need to be implemented by a Dialog class, however. For example, it is not uncommon to implement one with an Activity whose theme is set to that of a dialog. In this case, displaying the dialog-as-an-Activity will cause the new Activity to be on the top of the stack, pausing what previously was there.
I've been doing quite a lot of code with dialogs, including the AlertDialog that you mention, and I've also tried to check if onPause() is being called on the activity when the dialog pops up, but thus far my conclusion is that the activity simply keeps running and that onPause() is not called.
Not sure if it helps, but at least you now know that there are others who experience what you're experiencing :-)
Its wrong that activity remains no longer at top of activity stack in onPause phase.
Condition an activity to be onPause state -
Activity partially visible e.g. dialog on activity.
The Activity object is retained in memory, it maintains all state and member information, and remains attached to the window manager.
e.g Home button pressed causes activity to go in onPause(). Still at top of stack.
In fig 1. Activity3 will be destroyed and removed from top stack
In fig 2. Now Task A goes to background but Activty X still on top of stack . If you override onPause() method int this state
Figure 1. A representation of how each new activity in a task adds an item to the back stack. When the user presses the Back button, the current activity is destroyed and the previous activity resumes.
Figure 2. Two tasks: Task B receives user interaction in the foreground, while Task A is in the background, waiting to be resumed.
I think I remember reading in an earlier version of the Android Lifecycle that onPause was called when none of the activity is on display. i.e. if a bit of your activity is still visible under a popup, onPause will not be called.
Maybe some other experts can vouch for this behavior?
In my slightly weird experience onResume gets called with dialog.setCanceledOnTouchOutside(true); but onPause never gets called.
That being said, I think the documentation might focus on system dialogs (e.g. low on battery).
#hackbot
onPause() is called when your activity is no longer at the top of the activity >stack. A Dialog by itself is not an Activity, so will not replace the current >Activity at the top of the stack, so will not cause anything to pause.
everything depends on implementation...
what is a Dialog ? is a Window added to Display by WindowManager///
so the window when it shows is on top of everything .... (Z order)
what is activity... is "thing" that also creates its window....
when a dialog is shown or it's window comes visible on top of an existing activity, then it overrides partial the activity window so existing activity will move to partially invisible state and you will get call to onPause() from ActivityThread.
but to be sure we also need to consider here a one think...
the state of window if is a standalone window shown on top or it is a child window and a parent of it is a activity window....
so when we know
the Window.LayoutParams (FLAGS) we use to add
and what IBinder is used for the Window to show
we will khow how the activity will behave when windows are shown each over other .. as each winndow has a callbacks they are used by activity or dialog to manage their states...
involved components:
android.os.IBinder
android.view.Window
android.view.Window.Callback
android.view.WindowManager
android.view.WindowManager.LayoutParams
android.view.Display
btw:
if you want to know the windows on screen [ applicable only for the process you own - as window belongs to process and those are Sandboxed - each processs is a separate JVM strictly saying "ART" ] you can use a replection see :
android.view.WindowManagerImpl
android.view.WindowManagerGlobal
onPause() is called every Time when an Activity goes background and Dialog or other Activity comes foreGround. This is done to give first priority to something with which the user is interacting. e.g: assume you are in homescreen (which in turn is an activity) of an application, the homescreen is said to be in foreground. and when you go to next screen by pressing some button or a dialog appears the next screen/Activity/Dialog comes to foreGround and homecreen goes to backGround, which just means homeScreen's onPause() method got called.