How to run callback on application launch? - android

I know Android's Activity model is a bit different from what I usually consider to be an "app".
I want to do something (in this case, check some notifications on a server and show them if available) when my app is "launched". What is a good way to accomplish this?
I likely don't want to do it in an activity's OnCreate, since each activity can be created any number of times - the code would get called more often than necessary.
The app also has multiple entry points - would I have to duplicate the check in each activity?
What I'm thinking of doing is setting up this code inside the Application object, along with a flag that tracks whether it's already been called - and just call it from each Activity's onCreate().
Is there a better or more "proper" way to do this?

The right, Android-approved way to do this is:
Create your own android.app.Application class
Override the onCreate method
In the AndroidManifest.xml, change the android:name attribute of the application element to the name of your class
Now, whenever your app is "started" (any one of your activites is started for the first time and no other instances are alive) onCreate will be called.
You may also find the onTerminate method useful.

Can you just check if the bundle passed to onCreate() is null?
It's not null "If the activity is being re-initialized after previously being shut down..."

There's probably no harm in putting it in onCreate; the Activity is really only destroyed when the OS needs the RAM for something else, not when the user goes to another app.
EDIT: You can also have a Service that runs when the device gets booted up, too. This might be a better option if you also want to check when the app starts, since you'll only have to call context.startService from the Activity to run the check. Just be sure to stop it when it's done if you don't need it to be persistent.

Related

Why is there no Android API for getting the current Activity?

The question, How can I get the current Activity? has been asked dozens of times on Stackoverflow and other sites and there are many proposed approaches. However, all of them have drawbacks in one form or another.
In this posting, I am assuming that there is no solution provided for this in Android's APIs, e.g., something like: Application.getTask().getRootActivity().
Wouldn't it be nice if there was :-)?
So, to be clear, I'm not asking for an answer to How can I get the current Activity?
Instead, I am asking for the reason that such a capability has not been provided. Given that each running app has a task (assuming that the task hasn't been emptied) and each such task has a root Activity, it would seem to be easy to provide access to that root Activity.
The fact that that such access is not provided, when it is so clearly desired, implies to me that there is something fundamental about the Android architecture that I don't understand.
What is it that I'm missing? Why is this information not provided by the Android APIs?
For background, here is a section summarizing some of the approaches that have been proposed. I found the following two links particularly informative (each of the approaches below is presented at one or both of the links).
Links
How to get current foreground activity context in android?
Android: How can I get the current foreground activity (from a service)?
Approaches
Static Hook
Reflection
ActivityManager
Other (Instrumentation, AccessibilityService, UsageStatsManager)`
ActivityManager
The ActivityManager approach only provides the name of the Activity class, not the current Activity instance. E.g., for a Context instance c:
c.getSystemService().getActivityManager()
.getAppTasks().get(0).getTaskInfo()
.topActivity().getClassName()
Reflection
My favorite is reflection, as proposed by _AZ, but that approach is fragile, given that it relies on internals. What I would like to see from Android is this approach provided via a standard API that developers could then safely rely on.
Static Hook
The most common approach is using a static hook to save a reference to the currently running Activity. The hook can be either per-Activity or per-Application. Memory leaks can be avoided by saving/destroying the hook's value (e.g., in onCreate()/onDestroy(), onStart()/onStop(), onPause()/onResume()). However, issues can arise when multiple Activities are involved (e.g., due to overlapping lifecycles -- see below).
I implemented a static hook approach which does the following (to be perfectly transparent, I haven't implemented #1 yet -- I am currently using a per-Activity static hook, which is a bug).
Provides a class that extends Application to provide the hook. The hook contains a Stack; each node in the stack is a simple ActivityInfo class which contains a reference to an Activity instance as well as the state of that instance (CREATED, STARTED, RESUMED).
Provides a class called ActivityTracker that extends Activity. I then extend each of my Activities with ActivityTracker. ActivityTracker uses its lifecycle callbacks to push/pop itself to/from the stack and to update its state -- my other Activities don't have to do anything.
In theory, this would allow me to always know the full state of the task's back stack -- the full set of Activities, including the root Activity, as well as their current state. In practice, however, there is a twist -- when one Activity starts another Activity, their lifecycles overlap. During that period, peeking at the stop of the stack can yield an unexpected Activity instance.
From: https://developer.android.com/guide/components/activities/activity-lifecycle.html#soafa, "Coordinating activities":
Here's the order of operations that occur when Activity A starts
Acivity B:
Activity A's onPause() method executes.
Activity B's onCreate(), onStart(), and onResume() methods execute in sequence. (Activity B now has user focus.)
Then, if Activity A is no longer visible on screen, its onStop() method executes
Of course, this could be managed also. The bottom line is that we do have a global context available for storing information (the Application) and we do have full information about Activity lifecycle transitions, so with enough effort I believe that this static stack-based approach could probably be made pretty bullet-proof.
But in the End
But in the end it feels like I am simply rewriting code which probably already exists internally for managing an Activity back stack, which is why I ask (in case you've forgotten):
Why is there no Android API for getting the current Activity?
UPDATE
In this update, I'll summarize what I've learned from this thread and my own experiments and research. Hopefully, this summary will be useful to others.
Definitions
I'm going to use the following definitions for "Activity Visibility States", based on the Activity State definitions at https://developer.android.com/guide/components/activities/activity-lifecycle.html.
-----------------------------------
Visibility State Definition
-----------------------------------
Not Visible Created+Stopped
Partially Visible Started+Paused
Fully Visible Resumed
-----------------------------------
Issues
The very definition of "Current Activity" is murky. When I use it, I mean the single Activity in the Fully Visible state. At any given instant, there may or may not be such an Activity. In particular, when Activity A starts Activity B, A's onPause() gets called and then B's onCreate(), onStart() and onResume(), followed by A's onStop(). There is a stretch between A's onPause() and B's onResume() where neither is in the Fully Visible state, so there is no Current Activity (as I define it). Of course, there are also situations where a background thread may want to access a Current Activity and there may or may not be an Activity at all, much less a Current Activity.
I've also realized that I may not always need a Current ("Fully Visible") Activity. In many cases, I may simply need a reference to an existing Activity, whether or not it is currently visible. In addition, that reference might be to just any Activity (for situations where I need to pass a generic Activity reference to some API method) or it might be to a specific Activity subclass instance (so that I can trigger some code specific to that Activity subclass).
Finally, there is the need to understand when Activity lifecycle callbacks are called by the main UI looper and how events like configuration changes are handled. For example, if I create a DialogFragment using an Activity intance which is currently in the "Not Visible" state, will it ever get displayed and, if so, when? Along similar lines, it turns out that the onDestroy() and onCreate() methods caused by a configuration change are contained in the same message in the UI's message queue (see Android UI Thread Message Queue dispatch order), so no other messages will be processed between those two callbacks (during a configuration change). Understanding this level of processing seems to be critical, but documentation on it is sorely lacking, if not missing completely.
Approaches
Here is a collection of approaches that can be used to address most of the above situations.
Background
For discussion, assume Activity A and Activity B, where A creates B.
Generally speaking, a "global" variable can be created by making it
"public static" on pretty much any class. Conceptually, extending
the Application class and adding it to the extended class would be
good, but if that's too much work it could be included (for
instance) in one of the Activity classes.
Generic Activity Reference
Useful whenever a generic Activity is needed.
Create a global variable. In both A and B, have onCreate() set it to "this" and onDestroy() set it to null.
Topmost Activity Reference
Useful whenever you want to access the currently visible Activity.
Create a global variable. In both A and B, have onResume() set it to "this". This approach works fine unless all Activities exit, in which case you may need to create a separate flag to indicate that situation. (That flag could be the Generic Activity Reference implementation mentioned above.)
Specific Activity Reference
Useful whenever a handle to a specific Activity subclass instance is needed.
In both A and B: create a global variable in the Activity subclass itself. Have onCreate() set it to "this and onDestroy() set it to null.
Application Context
Useful whenever a Context spanning the lifecycle of the entire app is needed or when you don't care about using a specific Activity Context (e.g., to create a Toast from a background thread).
You can get this from Activity's getApplication() and store it on a static hook.
Handling Configuration Changes
There may be times when you want to stop/start a background thread only across an Activity "session", where I define "session" to include the series of Activity instances which may be created and destroyed due to configuration changes. In my particular case, I have a Bluetooth Chat Activity and an associated background thread to handle the network connection. I don't want to have the connection destroyed and created each time the user rotates the device, so I need to create it only when one doesn't exist and destroy it only if a configuration change isn't underway. The key here is understand when onDestroy() is called due to a configuration change. This can be done with or without fragments. As is often the case, I prefer the non-fragment approach since the fragment approach doesn't seem worth the extra complexity to me.
Approach 1: Without Fragments
In onCreate(), create the background thread if it doesn't exist yet. In onDestroy(), destroy the background thread only if isFinally() returns false.
Approach 2: With Fragments
This works well because the FragmentManager will store fragment instances across configuration changes if setRetainInstance(true) is used. For an excellent example of this, see http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html. The example is for AsyncTasks, but can also be applied to managing a background thread (just create the thread instead of an AsyncTask in the fragment's onCreate() and then destroy the thread in the fragment's onDestroy()).
Closing
Fully understanding these issues requires a deep understanding of how the UI looper processes its message queue -- when Activity callbacks are called, how other messages are interleaved with them, when display updates occur, etc. For instance, if a DialogFragment is created using an instance of a non-visible Activity, will it get displayed at all and, if so, when?
Perhaps some day Android will provide a deeper API to Tasks and their associated backstacks, along with documentation describing the UI's message processing and associated mechanisms in more detail. Until then, more "source code and/or ... empirical analysis" :-).
Thanks,
Barry
If all you want you want to know is which Activity is foremost and accepting user interactions, just create a BaseActivity that extends Activity and override onResume() and save a reference to "this" in a static variable. All of your other activities should extend BaseActivity. You're done.
The short answer I would guess is that only one activity can ever be active at a time in a given app, and that activity obviously knows who it is (it is itself) -- so the only answer any activity can get to "what activity is currently active" can only ever be "you are, silly".
For simple apps with a clear division between the different activity classes, this works fine, and so that's a great percentage of most of the apps in the play store. It doesn't work so hot when you're getting real clever with encapsulation and polymorphism, as I'm sure you've discovered, but I don't think Google is really targeting those types of developers.
Just my $0.02, I don't think you'll get an "official" answer here.

How to handle the background to foreground thing in android for all activities

Actually I am connecting with my application server each and every time when my application is coming from background to foreground for checking the session validity no matter on which activity user is currently on.
So What I did I have created one boolean type preference and setting up it true in to onCreate() method of activity and checking it on onResume() if it is true that means the application is coming from onCreate() which indicate the first time launch of activity so I am not running the set of code for validation and at the same time I am setting up that preference as false .
So if the application is coming from background to foreground the code will execute and check the validation of session.
But I feel it very messy when I am adding activities to my application each and every activity i need to take care of all these stuff not feeling it as a standard way of doing the same. Is there any function provided in Android which can help me out and fulfill my requirement ?
If not what should I do in the code level so I need not to worry about all these thing while adding the activities in my application means suggest some good way to achieving the same.
Consider creating a BaseActivity that will handle all the initialization and checking stuff that all activities should do. Now let all your activities extend the BaseActivity, instead of directly extending Activity.
This way if you'll need to add a new activity, the only thing you'll have to do will be to extend BaseActivity.

How to know when an application finished?

I need to know when an application finishes to stop all the local services that it starts.
How can I do it?
You could try using onDestroy() (not recommended, though) to know when Android is cleaning your app from the memory. or can also use onStop() to know when the Activity is being sent in the background.
Do implement these two methods in the first activity of the Activity stack.
Lets see if it helps, since I also haven't tried it so far.
One idea is to use BoundService despite the fact that it's your app own service. By definition Bound Service stops when the las connection is dropped.
Another idea would be to define count in Application object (you can override global Application object). You can increment the count in each onResume and in decrement in each onPause.
You could use try / finally on the main function and do the service clean up in the final block
You could use object finalizer to issue shutdown commands. You wont know exactly when it happens since the Garbage collector will run at its own pace, but you do know it will happen eventually.
I am now solving the same problem, I have an Idea and will implement it:
1.static variable called (String currentShownActivity).
2. in every Activity (onResume() ) I fill the variable with activity name). So when I navigate between the activities the currentShownActivity variable changed and carry the current activity name.
3. on every onPause(), set flag that indcate the activity onPause() called (i.e boolean IsPauseCalled)
4.in onStop () check IsPauseCalled, and the activity name.
if the activity onPause called and the name in currentShownActivity not changed (that mean we leave the activity to "no activity") and that mean [home] key pressed.
the integration way to know the the application is not running Check onDestroy of the main activity.

Application pause/resume state

My question is can i get to know when the entire application gets paused/resumed start/stop etc.
For example if i have 5 activities in my application. Whenever any activity gets paused/resumed android notify the activity by calling the onPause/onResume methods.
So there are two possible scenarios when my activity gets paused.
1. My activity-2 gets paused because my activity-3 gets invoked.
2. My activity-2 gets paused because of some outside activity like incoming call.
Here I am interested only tracking when my activity gets paused by outside activities not my own application activities.
So is there any android provided solution for this or do I have to write my customized solution.
Thanks
Dalvin
There is no solution provided by the API because it is not needed in most cases.
What you can do is to create an abstract activity and make all your activities inheriting from this abstract one.
In this abstract activity, by overriding onCreate, onResume, onPause, onDestroy, you can manage to count how many of your own activities are "alive", and then determine the state of your application.
This could work but it's not really the Android phylosophy
You can know the starting of the whole application on application.oncreate() but there is no indicator for the whole application pause. Most of the cases never needs it anyway.
So further read in the activity lifecycle and the application class.
Still you can do this option in your program by overriding the onPause in each class and save a value to the sharedPrefrences then check on this value all over the application
If I understand your question, you want your app to be able to distinguish between exiting the current activity within the context of your program or by an external event like a phone call. I have used the following method in the past to do this (although it may not be the best, it definitely works):
(1) Set up a value in SharedPreferences (the built in file for storing a program's data). Call it something like "exitStatus" which is set to 1 for an exit within the program code and 0 for an exit based on external events.
(2) Now, within each of your activities, set the value of exitStatus to 0 in onResume (which is called no matter how you enter). If your program exits due to an external event within that activity, this value will persist when the program is reloaded.
(3) At the end of your activity, at all points where you are going to transfer to another activity, first set exitStatus to 1. Then, when you arrive at the other activity, it will know that you arrived there from within your program.
(4) Thus, just to be clear, each of your activities can check exitStatus at the outset to see whether you are entering from within your program context (= 1) or after a non-local exit of some kind (= 0).
That's all there is to it. I use this method to be sure that load data for my app is present as it may be lost if a user turns off their device so that the app tries to pick up in the middle of things when they later reboot, etc.
Instead of making base activity and override onPause/onResume you can use
registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks callback)
where you can handle these states for application activities in one place.

android: unusual way to start activity

In one activity I need to start another one but with one condition: if it was started before then it must be finished and started again. This activity show some information about system state (Theme.Dialog style) it also can start some services and so on. As far as I know when I do startActivity(intent) then onResume() will be called (if activity was started before). Does anybody know how to do it?
That's precisely how it should work. If you need to adjust the values on-screen, put that code in onResume(). What may not be obvious from its name is that onResume() is called when the Activity is first created as well. It's always the last method called before an Activity becomes active.
use the NEW_TASK_LAUNCH flag in the startActivity() call. Read documentation http://developer.android.com/guide/appendix/faq/framework.html#4
In the manifest file, in the activity attributes, you have the attribute launch mode, which let you specify how the activity must be launched (http://developer.android.com/guide/topics/manifest/activity-element.html#lmode).
Take a look at the description to see which mode suits most your needs. Then when the activity is brought to front, you can restart your service by overriding the Activity.onResume() method.
In one activity I need to start another one but with one condition: if it was started before then it must be finished and started again
There is nothing that only does this. The closest is to have the combination of FLAG_ACTIVITY_CLEAR_TASK|FLAG_ACTIVITY_NEW_TASK, but that has other side effects, such as wiping out any other activities.
As far as I know when I do startActivity(intent) then onResume() will be called (if activity was started before).
Not by default. By default, a second instance of the activity is created.

Categories

Resources