I have an application that uses a Service to fetch data in the background both while the application is running and when it's not.
When it is not running i would like to show a notification when there is new data, but not when the app is running.
How do i determine in my service whether the app is running or not?
I think you want to check whether a certain activity is shown. If that is true, I would use the Activity.onCreate() method to set a flag in the application instance, i.e. extend the class Application with a field "uiRunning" and check this field in your service. onDestroy() should be used to unflag the attribute. Don't forget to use your Application class also in the Manifest.xml
I would agree with the use of onCreate()/onDestroy() for a single Activity application, though an Application with multiple activities would be better off using Application.onCreate()/onTerminate() in order to avoid triggering the uiRunning state when switching activities.
This is dead easy. You use a named Mutex.
Put this in the application you want to check:
bool createdNew;
Mutex mutex = new Mutex(true, #"Global\YourAppNameHere", out createdNew);
if (createdNew)
{
var app = new YourProcess();
app.run();
mutex.Close();
}
Put this in the application that checks to make sure the other app is running:
bool createdNew;
Mutex mutex = new Mutex(true, #"Global\YourAppNameHere", out createdNew);
if (createdNew)
{
Console.WriteLine("App not running");
mutex.Close();
} else {
Console.WriteLine("App is running");
}
Another option is to implement a listener pattern and have your service manage a list of listeners with methods on your service interface for addListener() and removeListener(). Your activity can add itself as a listener after it connects to the service and remove itself onStop() (i.e. when the app is no longer visible to the user or has shutdown completely).
In your service, check the count of listeners. If there are no listeners then you know you should create your notification.
Another way to accomplish is to de-couple your data receiver to a 'service' which will always run in the background. you can have your application bind to the service and will display the data fetched by the service.
The problem with having the application in background is that Android will kill the application once it gets too old. Its always better to have such background running application as service rather then activity.
What i did do was to use a flag in my service, that the root activity sets and clears on onStart/onStop. This works pretty well.
This is how I did it and is working flawlessly with just a few lines of code:
In extended App class:
public static boolean isAppInFront = false;
In you main activity:
#Override
public void onStart() {
super.onStart();
MyApplication.isAppInFront = true;
}
#Override
public void onStop() {
super.onStop();
if (isFinishing())
MyApplication.isAppInFront = false;
}
Related
I have kind of a tricky situation in my app.
I implemented a mechanism that contacts a remote server every 60 seconds to check if new data is available. If so, the new data is displayed in the app. So far so good.
I implemented the mechanism the following way:
It gets started in the onCreate() method of my MainActivity.
The polling routine gets stopped in my MainActivity's onDestroy() method.
This makes sure the polling is always active as long as the app is running. Also, if I start another Activity from my MainActivity, I also want the polling to run.
My Problem:
When I exit my application via the Back-Button, everything works fine and the polling stops. But when I exit my application through the Home-Button, the polling routine stays alive since onDestroy() of my MainActivity is not called, but I want it to stop.
If I change my code and stop the polling routine in the onPause() method of my MainActivity, I have the problem that the polling also gets stopped when I launch a new Activity.
What I want:
I want the polling to run as long as my Application (not my MainActivity) is in foreground / visible to the user. As soon as the User exits the application by pressing the Home-Button from anywhere in the App, or by pressing the Back-Button from the MainActivity, I want the polling to stop.
ADDITIONAL:
I also do not want to restart and stop the service everytime I switch Activities. Since the user of my Application will switch Activitys very often, this would just be a lot of overhead. Furthermore, I want the "refresh"-cycle to be exactly 60 seconds. I cannot guarantee that when I always restart the service and stop it again. It needs to be started once when the app gets started, and stopped when the app is no longer in foreground.
How to achieve that?
Isn't there some kind of simple way to check when the App is in foreground and when its hidden / closed?
This is my singelton-polling mechanism:
private Timer t;
private static Updater instance;
protected Updater() {
// Exists only to defeat instantiation.
}
public static Updater getInstance() {
if(instance == null) {
instance = new Updater();
}
return instance;
}
public void startPollingRoutine(int interval, int delay) {
t = new Timer();
// Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
update(); // some asynctask that does the updating
}
}, delay, interval);
}
public static void stopPollingRoutine() {
t.cancel();
}
In code:
Updater.getInstance().startPollingRoutine(60000, 0);
Updater.getInstance().stopPollingRoutine();
I think the best way how to handle it is to create some BaseActivity which all activities will extend. And to perform this actions in onResume/onPause. Or you can try using services.
you need to create a service and trigger it in your main class that service will be triggered unless you explicitly stop it on destroy means onBackpressed()/onDetroy() and let it run in onPause() method
Use a singleton, and let it have a counter variable. Increase it when you send intent to start a new activity, and decrease it in the onPause.
Than you can tell if the polling has to stop; when the counter in the singleton is zero.
Thank you all for your help and time.
I finally found a solution by myself that meets all my requirements.
I followed this tutorial to make it work: http://www.mjbshaw.com/2012/12/determining-if-your-android-application.html
The basic Idea is to extend the Application class and keep reference to how many Activitys are "alive" at a certain time.
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
I'm working on an Android project that consists of several different Activities all associated with the same Application. We have some common tasks coded in the Application so that we don't have to duplicate them, and one of these tasks is regularly verifying a TCP connection to a dedicated server -- a heartbeat, I suppose.
If it's detected that the connection to the server is lost, I need to notify the user and I'd like to do this in a way that doesn't require me to check all the possible activities to see which is currently "on top".
Is there a way to call runOnUiThread() on whatever activity may be on the UI thread without knowing it explicitly??
Thanks,
R.
Regularly verifying a TCP connection
Sounds like this should be implemented using a service..
If the alert is very simple, and has minimal importance, I would suggest using a Toast.
If the alert is crucial, but it doesn't require the user's immediate attention, use a Notification.
If the alert demands immediate user attention, you should use a Dialog. You won't be able to start a dialog directly from a service or broadcast receiver because they don't have a window associated with them, but you can use an intent to start an activity on a new task. You can style the activity to be whatever you want. It could even look like a dialog box (or show a dialog box when it's started). Starting the activity in a new task will make sure the user can navigate back to whatever they're doing.
You can notify your Activities by sending Intent and registering BroadcastReceiver in each Activity you want to be notified.
service or application can be your context:
Intent i = new Intent("MY_ACTION_FROM_SERVICE_STRING");
context.sendBroadcast(i);
activity:
public class MyActivity extends Activity {
private ActivityBroadcastReceiver recvr;
public void onReceiveCommand() {
//do something
}
#Override
public void onCreate(Bundle b) {
super.onCreate(b);
recvr = new ActivityBroadcastReceiver(this);
this.registerReceiver(recvr,
new IntentFilter("MY_ACTION_FROM_SERVICE_STRING"));
}
}
receiver:
public class ActivityBroadcastReceiver extends BroadcastReceiver {
private MyActivity target;
public ActivityBroadcastReceiver(MyActivity target) {
this.target = target;
}
#Override
public void onReceive(Context context, Intent intent) {
target.onReceiveCommand();
}
}
One of the simple way (which I've adopted for my project too) is to create a base Activity class (preferably Abstracted) and then make your normal activity classes to extend it. By this, you may put a general piece of code in the abstracted class which may help you to detect currently visible activity.
Moreover, you may set a BroadcastReceiver in your base activity class which will always be ready to listen broadcasts regardless of setting it individually in your child activities and then set it to listen for broadcasts sent from your tcp thinggy.
Do not do any trickery. Implement Observer pattern, so any activity would register its listener in onResume() and unregister in onPause() and whatever will happend your Application object code needs just to tell about that to registered listeners, no matter what Activity they are in
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!!!!");
}
}
}