I am needing help to determine the right approach. I want to make a backup of an internal database to a location in the external storage every time the whole application gets interrupted or terminated/destroyed. I want to call this method from a central class called Main which extends Application. The reason for that is, that I need to use several activites and I want to call the backup Method only when needed (like described when the whole application gets destroyed or interrupted by another application). I try to avoid calling this backup method in every activity in their onPause() methods.
I thought about starting a service in the onCreate() method of the application, and starting the backup method when the service gets destroyed. But this won't help in the case of an interrupt, as far as I understood the logic behind services. And also the service doesn't seem to start. startService(new Intent(getApplicationContext(), BackupService.class)); Furthermore I don't think it is a good approach to just use the onDestroy() method of a service, this is not what the service class is made for in my opinion.
So summarizing my Question, do you know a better way then using a service, or if not do you know how I should use the service to be able to call a backup only at the point when the whole app (and not only an activity) is interrupted or destroyed.
First of all, if your service "doesn't seem to start", you are probably doing something wrong.
To accomplish your goal make a backup of an internal database to a location in the external storage every time the whole application gets interrupted or terminated/destroyed:
There are three cases in general here.
If you want to do it in the activity layer:
To know when your application is crashed, you need to implement a custom handler to catch the uncaught exceptions.
To know when your activity is "interrupted", the only way is do it in onPause.
To know when your activity is "terminated", the only way is to do it in onDestroy.
This will require you to have a clear navigation and only do it in your "main activity", and all the other activity starts and comes back to it OR use a flag to indicate if the pause was caused by going to another activity.
If you want to do it in the service layer: (Your way of doing it onDestroy won't allow you to detect interrupted case since you will have to start service sticky to keep it running)
You will have to set up a flag on each activity onBind (you will have to bind it and unbind it) to know if it is a crash/interrupt/termination, which will complicate other part of your code.
To avoid running repetitive code, you will have to create a generic base class and extend your other activities from it.
I use this approach to play background music in one of my games, but I guess it works in this scenario as well.
Use a boolean flag to indicate whether or not your app is launching another part of your app.
boolean movingInApp = false;
....
movingInApp = true;
Intent intent...
.....
public void onPause() {
if(!movingInApp) {
//start service
}
}
public void onResume() {
movingInApp = false;
//Stop service
}
By setting the value of movingInApp to true before launching any intent etc, you can prevent your app from starting the service. Remember to set it to false again later in your onResume() method. If the system makes your app go to the background, this will be false, and your service will be started.
Why dont u have all of your activities extend a base activity which in turn extend the android activity class
I the base activity have backupDB method in the onPause
Therefore u dont have to put it in every activity pause method
Related
I'm developing an android app using bluetooth communication (using a propetary protocol) and I need to catch the moment when the app is killed.
I wanted to use the "onDestroy()" method but it isn't called every time the app is killed.
I noticed that it is called when I press the back button and, only sometimes, when I kill the app from the task manager.
The question is: How can I catch the moment before the app is killed?
Here is the code I tried to use:
#Override
public void onDestroy() {
sendMessage(msg);
Log.d("SampleApp", "destroy");
super.onDestroy();
}
#Override
public void finish(){
sendMessage(msg);
Log.d("SampleApp", "finish");
super.finish();
}
Unfortunately finish() is never called and onDestroy isn't called every time I close the app from the task manager.
How can I handle this?
As stated in the documentation here, there is no guarantee that onDestroy() will ever be called. Instead, use onPause() to do the things you want to do whenever the app moves into the background, and leave only that code in onDestroy() that you want run when your app is killed.
EDIT:
From your comments, it seems that you want to run some code whenever your app goes into the background, but not if it went into the background because you launched an intent. AFAIK, there is no method in Android that handles this by default, but you can use something like this:
Have a boolean like:
boolean usedIntent = false;
Now before using an intent, set the boolean to true. Now in your onPause(), move the code for the intent case into an if block like this one:
if(usedIntent)
{
//Your code
}
Finally, in your onResume(), set the boolean to false again so that it can deal with your app being moved into the background by a non intent means properly.
Your application will not receive any additional callbacks if the process it terminated by external means (i.e. killed for memory reasons or the user Force Stops the application). You will have to make do with the callbacks you received when you app went into the background for your application cleanup.
finish() is only called by the system when the user presses the BACK button from your Activity, although it is often called directly by applications to leave an Activity and return to the previous one. This is not technically a lifecycle callback.
onDestroy() only gets called on an Activity as a result of a call to finish(), so mainly only when the user hits the BACK button. When the user hits the HOME button, the foreground Activity only goes through onPause() and onStop().
This means that Android doesn't provide much feedback to an Activity to differentiate a user going Home versus moving to another Activity (from your app or any other); the Activity itself simply knows it's no longer in the foreground. An Android application is more a loose collection of Activities than it is a tightly integrated singular concept (like you may be used to on other platforms) so there are no real system callbacks to know when your application as a whole has been brought forward or moved backward.
Ultimately, I would urge you to reconsider your application architecture if it relies on the knowledge of whether ANY Activity in your application is in the foreground, but depending on your needs, there may be other ways more friendly to the framework to accomplish this. One option is to implement a bound Service inside of your application that every Activity binds to while active (i.e. between onStart() and onStop()). What this provides you is the ability to leverage the fact that a bound Service only lives as long as clients are bound to it, so you can monitor the onCreate() and onDestroy() methods of the Service to know when the current foreground task is not part of your application.
You might also find this article written by Dianne Hackborn to be interesting covering in more detail the Android architecture and how Google thinks it ought to be used.
I just resolved a similar kind of issue.
Here is what you can do if its just about stopping service when application is killed by swiping from Recent app list.
Inside your Manifest file, keep flag stopWithTask as true for Service. Like:
<service
android:name="com.myapp.MyService"
android:stopWithTask="true" />
But as you say you want to unregister listeners and stop notification etc, I would suggest this approach:
Inside your Manifest file, keep flag stopWithTask as false for Service. Like:
<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) {
//unregister listeners
//do any other cleanup if required
//stop service
stopSelf();
}
Refer this question for more details, which contains other part of code, too.
Start service like below
startService(new Intent(this, MyService.class));
Hope this helps.
I'm working on an application which has a few Activities. One Activity starts the next one. To share some Values I'm using a custom implementation of Application (I'm talking about android.app.Application) called MyApplication.
As we all know, the Android system kills an app, if it needs more space. But this leads to a problem:
I open my app and use it just like any other app
I close it (Home Button) and use other apps
The system will kill my application because it's wasting memory
When I reopen my App, it wants to open the last activity I used and I get a force close, because the values in MyApplication are null
The strange thing is, that the system destroys my Application, but it seems like it keeps the Activity. I don't really understand why this is so because the Application doesn't seem to have a life cycle.
What I want to have:
When MyApplication (whole Application, not only the activity) gets killed, I want the last activities to be killed too. So when I reopen the App, it starts the main acitvity provided by the manifest.xml.
or
The values in MyApplication are persisted and don't get lost if the Application gets destroyed. (I'm talking about a few objects so i think the shared preferences won't work).
I don't want to use a service to bind my activities to, but is there a similar way to tell the system that my last used activity depends on the application-context?
I hope you understand what my problem is and someone can help me out with this.
The right way to do things would be to save your application state.
Override the onSaveInstanceState(Bundle savedInstanceState) method to save your state and onRestoreInstanceState to retrieve it.
If you need to save large sets of data consider using a SQL database
You should make sure the app closes and restarts the way you want it to in the onPause() , onResume() and onStop() methods. Check out savedInstanceState which can save the state of the app (and restore it, when it's sent as a parameter to onCreate)
In your custom implementation of Application, add a Flag say :
public boolean appContextExist = false;
On your first Activity set the flag to true,
Override onCreate and onResume method on your Activity which need the contexts, add following :
MyApplication myApp = ((MyApplication) getApplicationContext());
if (!myApp.appContextExist) {
// Code to return to start activity here
}
I.e I would like to know when user interact with my application and when not.
I have tried do it using ActivityManager.getRecentTasks(). I have checked root activity at a top task to detect interact user with my application or not.
I have forced to check it in separated thread each second or two.
This way is bad for me. There is another way to detect when any activity of my app are opening or closed?
Have a look at the lifecycle of an Activity.
There are callback methods (onStart, onResume, onPause, onDestroy, ...) that are invoked by the system whenever your activity is created, becomes active or inactive etc.
You might create your own application class (just inherit from android.app.Application) and do your tracking there. The application will be around as long as your app is running.
For example you could put a flag or a counter there and set it from the activities' callbacks. A simple example for that could be:
public void onResume() {
super.onResume();
((MyApplication)getApplication()).active = true;
}
public void onDestroy() {
super.onDestroy();
((MyApplication)getApplication()).destroyed += 1;
}
Is there any way to handle when my android application goes into background and back?
I want to use notification service for a on-line game - I use a service, which shows an alert when something happens in the game. I want alerts to show only if my application is active (on the foreground), so I need to start my service when application goes foreground and stop it when application goes background.
Note that I cannot use Activity.OnPause/OnResume methods. I have many activities in my application, and if I'll handle OnPause/OnResume, it is possible in a moment, when a user swtches one activity to another, application will look like background, thorough it will be foreground actually
Note that I cannot use Activity.OnPause/OnResume methods. I have many
activities in my application, and if I'll handle OnPause/OnResume, it
is possible in a moment, when a user swtches one activity to another,
application will look like background, thorough it will be foreground
actually
Why don't you write a base class that extends Activity and enables or disables the service in these methods? After that extend all your activities from this base activity.
All you have to do is call the superclass method if you override these methods in your activties, e.g. by calling super.onResume() inside onResume(), to make sure these get still called. If you don't override them, everything works directly.
Not a clean way of doing this that I know of but,
You could perhaps send an Intent to your Service onCreate() and onPause() with a unique identifier.
You Service can then start a timer (with a delay which will be longer than the difference between onPause and onCreate being called in each activity) which, if not notified of an onCreate() within this time will set the Activity as "Paused".
If you add this functionality in a parent class which extends Activity you can then pull this same functionality into every class by extending that it rather than Activity (with the contract that you must call super.onCreate() and super.onPause() in each respective method).
Problem solved in a following way (C# code, mono for android)
class MyService : Service{
OnSomethingHappened(){
ActivityManager am = (ActivityManager) GetSystemService(ActivityService);
if(am.RunningAppProcesses.Any((arg) =>
arg.ProcessName == "myprocessname" &&
arg.Importance == ActivityManager.RunningAppProcessInfo.ImportanceForeground
)){
Trace("FOREGROUND!!!!");
}else{
Trace("BACKGROUND!!!!");
}
}
}
I have a Service which tracks the location of the user. Currently, the Service boots when the application starts and stops when the application terminates. Unfortunately, if users keep the application in the background, the Service never stops and drains battery.
I would like the Service to stop when my application is not in the foreground. I was hoping the Application class would let me Override onPause and onResume handlers, but it does not have them. Is there another way I can accomplish this?
I haven't tested this yet, but it looks like if you use Context#bindService() (instead of Context#startService()), the service should stop when no more activities are bound to it. (see Service lifecycle).
Then use onPause()/onResume() in each activity to bind/unbind from the service.
Alternatively, you could add a pair of methods on your service which tell it to start/stop listening for location updates and call it from each activity's onResume()/onPause(). The service would still be running, but the location updates wouldn't be draining the battery.
Reading all the above answers I would suggest Simply add a boolean global flag for each activity & put it in your onResume & onPause & also while launching an Activity Something like this
public void onPause()
{
super.onPause();
activity1IsResumed = true;
}
&same for onResume
& similarly when launching a new Activity
startActivityForResult(myintent ,0);
activity2IsResumed = true;
activity1IsResumed = false;
then in your Service simply check
if(activity1IsResumed || activity2IsResumed || activity3IsResumed)
{
//your logic
}
else
{
//another logic
//or dont run location tracker
}
& you are done!
You should override the onPause and onResume methods on your Activity. If you have multiple activities you may want to have a common base class for them and put the start/stop logic into the base class.
I have not tried this approach but I think you can override the home key of android device by using KeyEvent.KEYCODE_HOME and you can use stopService(Intent) to stop your service and when again application resumes, you can write startService(Intent) in the onResume() method of your Activity.
This way I think your service will only stop when user explicitly presses home button to take application in the background and not when he switches from one activity to another.
What I would suggest is overriding the onPause/onReume methods as others have said. Without knowing more about the flow of your application and interactions between Activities, I can't give much more information beyond guesswork.
If your Activities are persistent, however, my recommendation would be to utilize the Intents better when switching between Activities.
For instance, each Activity should have a boolean "transition" flag. So, when you move from one Activity to the next, you set up an Intent extra:
intent.putExtra("transition",true);
Followed in the receiving Activity by: (in onCreate)
intent.getBooleanExtra("transition",false);
This way, for each Activity that launches, you can know whether it has come from another Activity, or if it has been launched from a home screen launcher. Thus, if it gets a true transition, then onPause should NOT stop the service--that means you will be returning to the previous Activity after it returns. If it receives no "transition" extra, or a false transition, then you can safely assume there is no Activity underneath it waiting to take over for the current one.
On the first Activity, you will simply need to stop the service if you are switching to another Activity, which you should be able to figure out programmatically if one Activity is started from another.
It sounds like the real problem is how to only stop the service when you go to an activity that isn't one of your own? One way would be to in your onPause method to stop the activity. Do this for all your activities. Then override your startActivity method. And in here do a conditional test to confirm that you are purposefully navigating to one of your own. If your are set a flag to true.
Now go back to your on pause overridden method. And only stop your service if the flag is not equal to true. Set the flag to false.
All events that navigate away will close your service. Navigating to your own will leave it intact.
Do the overriding in a base class that all your activities extend.
Writeen in my andolroid. Will post ezaple later.
Try using the Bound Services technique to accomplish this.
Bound Services | Android Developers
You can use bound services in a way such that the service will stop when no activities are bound to it. This way, when the app is not in the foreground, the service will not be running. When the user brings the app back to the foreground, the Activity will bind to the service and the service will resume.
Create methods registerActivity() and unRegisterActivity() in your Application object and implement first method in all you acts onResume() and second in acts onPause().
First method add activity to List<Activity> instance in your app object, unRegisterActivity() checks size of list in every call if==0 stopService();.