I need a method to detect when my application is closing, so that I can tell a web-server to clear my session variable that it's storing. Is there any way to do that?
I'm assuming your application extends Activity.
You could use the onDestroy() method:
From the docs :
onDestroy() is The final call you receive before your activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.
Your code would look like this:
public class YourAppActivity extends Activity {
...
...
#Override
protected void onDestroy() {
super.onDestroy();
//clear your session variable.
//you may want to do this quick, and on another thread
//to prevent android from killing your app
}
}
check
Activity Lifecycle and
i think you can do it on onDestroy()
You could try onDestroy() which is run when the app is being destroyed by the system or onStop() when the app loses visibility (often prior to destroying). You code would then look something like this:
public void onDestroy() {
super.onDestroy();
//Enter your code here to do stuff
}
However, on destroying your app the variables used by it will be destroyed along with it.
See: How to release or clear the value of variable or object?
For this you have to create static variable for counter of integer type. On OnCreate method Increment variable by 1 and on OnDestroy() Method decrement the variable value. and on OnDestroy() Method check the static variable value is 0 or not if it is 0 then call the webservice to clear the session
I would use the Activity's onDestroy() method checking whether the user is terminating the app or the OS is killing the process' activities because of low memory with the isFinishing() method. To deploy the "Destroy web session" logic, you could start an IntentService to start this action.
Hope it helps.
Related
I am trying to modify my firebase database when my app is destroyed, that means when I remove the app from the list of recent running app or when I click on Home button ,but I don't know how to do this, I tried to do that in onDestroy() method of every activity but it doesn't work.
This is my onDestroy() method :
#Override
protected void onDestroy() {
super.onDestroy();
FirebaseDatabase.getInstance().getReference().child("users").child(encodeEmail(mAuth.getCurrentUser().getEmail())).child("status")
.setValue("destroyed") ;
/*Toast.makeText(ContactsActivity.this,"closing app",Toast.LENGTH_LONG).show();
MyApp app = (MyApp)getApplication() ;
app.setUpBeforeClosing();*/
}
On Destroy Documentation
Do not count on this method being called as a place for saving data! For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here. This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.
Either use OnPause or Use a service to write data.
Add this in manifest
<service
android:name="com.myapp.MyService"
android:stopWithTask="false" />
Now in your MyService service, override method onTaskRemoved. (This will be fired only if stopWithTask is set to false).
public void onTaskRemoved(Intent rootIntent) {
//save data to firebase
//stop service
stopSelf();
}
reference
Do you have BaseActivity or not ?
I think you just forgot to add this line in the right activity.
I suggest you to create BaseAvtivity.java class and extend all your activities from it, and the BaseActivity would extends AppCompatActivity and then override tbe lifecycle methods in BaseActivity and set new value in onDestroy method.
This is a text I have copied and pasted from this training tutorial.
"Because the system retains your Activity instance in system memory when it is stopped, it's possible that you don't need to implement the onStop() and onRestart() (or even onStart() methods at all. For most activities that are relatively simple, the activity will stop and restart just fine and you might only need to use onPause() to pause ongoing actions and disconnect from system resources."
I don't understand it. Because to the best of my knowledge, an activity is only stopped by calling onStop() and is only started by calling onStart(). How can an activity start at all without an onStart method.
Do you people understand what they mean in this paragraph?
I think they are confusing you with the word "stop" which appears to have multiple meanings in the paragraph.
I would rephrase it as
Because the system retains your Activity instance in system memory
when it is not in the foreground, it's possible that you don't need
to implement the onStop() and onRestart() (or even onStart() methods
at all. For most activities that are relatively simple, the activity
will suspend and restart just fine and you might only need to use
onPause() to pause ongoing actions and disconnect from system
resources.
The point being is that the App can appear to be stopped, when in actual fact, the system has simply paused it and hidden it from the screen. When the user launches it again, the App doesn't need to start (because it technically hasn't stopped), so it is simply resumed.
When you make an Activity and extend the base class Activity, there is already code in the onStop(), onStart(), and onRestart() methods in the base class.
Your activity simply extends these methods, meaning that you could add more code to them by Overriding them.
So, even though Activities are only started and stopped through those methods, you do not have to explicitly override them in your application. In most cases you won't even have to worry about them: They will be called by the base class from which you are extending.
Please make sure, An Activity starts from onCreate method , then onStart is called by system. If you override onStart method then your overridden method will be also called after onCreate method. If you don't override , then default version of onStart is called.
onStop is called after onPause.
Please check this link , and take a look at Activity life cycle . Your concept will be clear.
Difference between onCreate() and onStart()?
you can use an Activity just fine without - if you need to do something special in onPause() you can override the method:
#Override
public void onPause(){
super.onPause();
// Your magic here!
}
Same goes for onStart(), onStop() etc. You don't need to override the methods but you can if you need to do something specific.
I have an activity in whose onCreate method an Init function is called (the function calls some native code involving lot of stuffs and calls to the openSLES audio api). The point is that this Init function makes the app crash when called again, which happens on a screen rotation or when i close the activity using Back button and i launch it again (but if in the meanwhile the process is killed, i have no troubles). I can't change the beaviour of the Init function.
I see that the process isn't killed when the activity is destroyed, I expected this after reading the docs, and it's a good thing since - if there is some audio signal playing - that continues playing after the activity has been destroyed, which is good for my purposes.
I tried to perform a check on the initialization state using onSaveInstanceState, but that works well only on screen-rotation, that's when onSaveInstanceState is called. The callback is not called when i push the Back button.
So i tried to use Shared Preferences, performing the state saving in onPause. But at this point i have the opposite problem: if the process is killed, the Shared Preferences values are kept, but in that case i need to perform Init again for the app to work properly.
I guess i need a way to know for sure if my activity is created after a process kill or not, but at the moment i can't see how. I thought about using the bundle instance in onPause method, but i can't figure how and whether this is possible. Any kind of hint would be really appreciated.
You can store pid of your process in shared preferences. If you compare in YourActivity.onCreate your current pid with stored one, you can determine when you must initialize OpenSLES.
You can initialize OpenSLES in Application-derived class, in YourApplication.onCreate - it's called only once.
edit:
I.e. declare following class:
public class YourApplication extends Application {
static private native synchronized void InitOpenSLES();
public YourApplication() {}
// see http://developer.android.com/reference/android/app/Application.html#onCreate() for details
#Override
public void onCreate() {
super.onCreate();
InitOpenSLES();
}
}
There's a simple solution to this problem. You don't need to save things in SharedPreferences to accomplish this. Just use a static (class) variable. Like this:
public class Globals {
public static boolean initialized = false;
}
The variable initialized will be set to false when the class is loaded. Only once. In your code, you then check and set the variable like this:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initialize (but only once per process)
if (!Globals.initialized) {
init(); // Call init function that does things one time per process
Globals.initialized = true; // Remember we are initialized so we don't
// do it again
}
...
}
Even if all your activities are finished, if the OS doesn't kill your process the variable initialized will still be "true" if the application is started again. Once the OS kills the process, the variable will be set to "false" the next time the application is started and a new process is created.
For each and every process you have pid or process id. In your init function you can easily get the thread id and can save it in any integer value.
Thread.currentThread().getId()));
whenever your activity will restart just check that thread id is same or different. If thread id is different then call your function init function. Otherwise you have already done.
I am using Application class to share global variables across activites and I am setting them in onCreate method of application class. When I start app variables values are set in onCreate and while using app in activities I am changing values of varables. When I exit app and start it again I am getting old values, the last values of variables set in activities. Thats mean onCreate of Application not running on starting app again. This is code in onCreate method of Application class.
#Override
public void onCreate() {
super.onCreate();
application = this;
category = 12;
subCategory =22;
}
It looks like old application object is still in memory and it is not calling onCreate on starting app 2nd time.
What is need to be done so that onCreate of application class run again or where to initialize variables in application class so that code runs everytime.
please declare your application class name in manifest file.
like below
<application
android:name="com.tt.app.TTApplication"
android:label="#string/app_name"
In the Application class, the onCreate() method is called only if the process was ended when you exited the application. Usually the process is stopped when the system needs memory or if you exit the app using the back button instead of the home button. However, you cannot rely on it being terminated.
However, the right way of passing parameters between activities are intents or preferences. In your case, I have the feeling that preferences is the way to go.
If you really want to kill your process when exiting the application, you can call
System.exit(0); when the user presses the back key on your first activity. This is definitely not recommended since it means fighting against the way the Android OS works and might cause problems.
More on this here: Is quitting an application frowned upon?
There is probably an instance of your application still in the memory.
Recheck your life cycle methods and make sure that the application is exiting properly.
Also check if any of your activities are leaking memory.
I had the same problem with my app where onCreate() method of Application class just triggered for the first time when my app is loaded. Daniel's solution of using System.exit(0) did the trick but this solution lead me to another problem. After using System.exit(0), onPause(), onStop() and onDestroy() method of my foreground activity did not get called.
Well, that was a reasonable behavior for an app because If you use System.exit(0) then you application will be removed from System's process queue and there will be no way for an android to execute onPause(), onStop() and onDestroy() method for my foreground activity.
The workaround I used for this problem was to finish my activity when back button is pressed and after some time killing my applications process like below:
public void killApp(){
final Thread threadKillApp = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, "Going to kill app");
android.os.Process.killProcess(android.os.Process.myPid());
}
});
threadKillApp.start();
}
Calling killApp() method just after calling finish() on my activity did the job.
Check the Activity life cycle. Do what you want in onResume() instead.
try to use onStart() method or onResume().
Your onCreate method should look like this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(someView);
}
your onResume Method should look like this:
#Override
public void onResume() {
super.onResume();
variable = someVariable;
}
I have an issue. For analytic purposes I need to track when the APP (not activity) is resumed. The problem I have now is that if I put the tracker on the OnResume event of an activity, it will get fired every time the user goes back and forth on different activities.
How can I avoid that? How can I track the real "Application Resume," (when user actually exits the app and come back) and not the activity resume?
Any ideas is greatly appreciated. Thanks.
I encountered the same problem and solved it by creating base activity :
public class mActivity extends Activity{
public static final String TAG = "mActivity";
public static int activities_num = 0;
#Override
protected void onStop() {
super.onStop();
activities_num--;
if(activities_num == 0){
Log.e(TAG,"user not longer in the application");
}
}
#Override
protected void onStart() {
super.onStart();
activities_num++;
}
}
all the other activities in my app inherited mActivity. When an activity is no longer visible than onStop is called. when activities_num == 0 than all activities are not visible (meaning the the user close the app or it passed to the background). When the user start the application (or restarting it from the background) onStart will be called (onStart is called when the activity is visible) and activities_num > 0. hopes it helps...
Use the Application object of your app (see http://developer.android.com/reference/android/app/Application.html). If you create a custom Application class and configure it in your AndroidManifest.xml file you can do something like this:
Start tracking in the onCreate() of the Application object.
Instrument all your Activities so their onPause() and onResume() methods check with the Application object and see if they are the first Activity to run, or if they are continuing a previously running instance of the app.
Stop tracking in the onDestroy() of the Application object.
To a certain degree most of the analytics packages (Flurry and their ilk) do something similar to this. You'll need to do a little state machine work to get this to work right, but it shouldn't be too complicated.
Instead of OnResume(), hook into the OnCreate() event of your main activity.