I have a service that is maintaining a socket connection to a game server. The game needs frequent two way communication to the server, so this connection should be kept open as long as the app has the foreground. However, since keeping the connection open is battery intensive we'd like to be as nice as possible and as soon as the app leaves the foreground (ie the user returns to the home screen) we would kill the connection.
This is all pretty close to working, but we're running into a couple small irritations. Whenever the game changes Activity's (such as to the preference activity) the connection drops. Now we could have each activity drop the connection onPause and and start up the service responsible for this, but that seems less than optimal since it will cause unnecessary dropping and reconnecting. Binding the service stop to the onStop method also seems way less than optimal since the connection will stay alive long after the user leaves the game.
What we're looking for is a way to start up a service at some point soon after out initial activity starts and keep that service running as long as the application is in the foreground. And as soon as the user leaves the application have the service shut down.
If you only need it to run while the app is in the foreground (i.e., one of it's activities is displayed), you don't really need a service. Make your connection manager class a singleton and count the number of activities that are using it as described here: https://groups.google.com/forum/#!msg/android-developers/yxOzuMGlcSo/yd-pkau0zzAJ
Services in Android are used when you need to run without a UI, so not really a good fit for your use case.
Related
I am currently using a foreground service to check every 30 seconds if a specific bluetooth device is in range.
When it comes in range I connect to it and read data to display to the user.
I've been reading up on background services, and even though during the actual connection it should be a foreground service, while waiting to connect it should be a background one.
so I made a different service (yes I know I could just move it into foreground when it becomes connected, but I prefer to use a different service for it) which is in the background and will continuously scan for the specific mac address, when it finds it it will start the working service which will run in the background.
I don't mind the system killing my service if it is low on memory (it is not that important, plus if the user wishes to connect they can force the connection through the ui which will start the foreground service), but I would like to make sure that when there is enough memory the service is started again, is START_STICKY enough?
In case the system destroys my service, where do I put the clean up code? will onDestroy always fire?
Finally how can I test low memory conditions for android so as to make sure the restart goes correctly?
this has been answered here please ignore it
I'm fighting with the Android desire of killing everything which isn't active on the screen. My problem in few words:
I have a microcontroller which communicates with a processor on which Android runs;
the processor must keep active a watchdog on the microcontroller, resetting periodically (every one second) one of its registers; an application, say App B, accomplishes this duty;
on the processor I can be sure about the persistent existence of another application, say App A (or, however, if App A dies App B can die too because the system is compromised) which for now does nothing, in the future will accomplish other duties.
Which is the best way to implement App B?
I tried the following solution: App B contains a Bound Service, say Service A, to which App A can bind on; Service A starts a thread, say Thread A, which periodically resets the microcontroller watchdog. Thread A is launched when app A sends a command to Service A (e.g. START_WATCHDOG).
In my idea, Service A lives until App A lives (thanks to the binding), and so the process to which Service A belongs lives, and so also Thread A.
Unfortunately, from tests I see that sometimes (in a sporadic manner), after some time (sporadic time, too), with almost no work running on the system (except for App A, Service A and Thread A) the system kills Service A process, and so Thread A stops and the watchdog elapses.
When Service A dies, it is restarted (because it is a Bound Service and App A is still running) but, for now, I don't save the current state of Service (which simply consists on the START_WATCHDOG command arrival or not) and this is the reason for which the watchdog elapses.
So, I've got several questions about my solution:
is it ok and I simply need to save the current state of Service A in order to restore it when restarted?
should I discover better the reasons for which Service A, or better its process, is killed?
is there a better solution for my problem?
Thank you very much to everyone who will spend some time to help me.
Being not sure about periods in which your service runs you can try these:
Use foreground service. However, you might need to acquire a wakelock within your service start point if you need cpu in long time. Plus, a notification needs to be shown on phone status bar.
Use WorkManager-new api part of jetpack simplifying the use of alarm managers and jobschedulers- to schedule your tasks periodically. However if your frequency is higher than 1 per 5-10minute then you will need to take care of doze mode. If phone gets into doze, your tasks might be delayed till maintenance periods. A trick to apply here might be starting a foreground service when you catch activation of doze mode and return back to Workmanager logic in deactivation(if you don't want user to see the foreground service's notification). Do whatever you want in the foreground service like.
Use Firebase Cloud Messaging to push notification from your server to your users periodically for you to have a small amount of time to do work in background. When notification comes, OS grants you an interval to run a task.
Use Work manager it is easy to implement.
I have started a service from my application and from that service a worker thread is started .I want my service to run even application goes background and until the user kills/exits the application.
But some cases my service got killed due to low memory ,then used sticky service or making the app to foreground to restart the service.
My issue is I dont want to lose the data between service ending and restarting time ,so is it possible to start another thread from service ondestroy method, but in this case how we can control that thread.
Please let me know is it the right approach ,and is this usecase achievable
I want my service to run even application goes background and until the user kills/exits the application.
This is not possible. The user can always get rid of your app, via Force Close in Settings, or via some device's version of the recent-tasks list.
But some cases my service got killed due to low memory
No, your process is terminated for low memory.
My issue is I dont want to lose the data between service ending and restarting time ,so is it possible to start another thread from service ondestroy method
No, because your process is being terminated.
Please let me know is it the right approach
Probably not. Very few apps need a service that runs constantly, which is why Android, and its users, go to great lengths to control such services. I would recommend that you try to find some solution to whatever your problem is that does not need a service running constantly.
I have an android application that binds itself to a remote service once the application starts. The remote service provides an abstraction to a bluetooth video camera so we can send commands and receive events from it easily. The binding happens from the Application itself as opposed to an Activity. It is important to me that as long as the camera connection to bluetooth is active that my application stay running so I can receive events from the remote service. The main reason is that I need to know if it's recording or not and if so I need to periodically send it GPS coordinates.
Will my application have a better chance of not being killed if I use a service within my own application to manage that? Or is my application safe from being killed since it is still bound to the remote service? Of course, I understand that the android system will kill my app if memory requirements require it to but will it ever kill my app just because it's been sitting for awhile not doing much?
The application's process should only be removed if memory is low, but you will raise the perceived importance of your process if you use a service rather than an empty process or a background activity. You can also use startForeground() to make it less likely that Android will stop your service.
From http://developer.android.com/reference/android/app/Activity.html#ProcessLifecycle:
Process Lifecycle
The Android system attempts to keep application process around for as
long as possible, but eventually will need to remove old processes
when memory runs low. As described in Activity Lifecycle, the decision
about which process to remove is intimately tied to the state of the
user's interaction with it. In general, there are four states a
process can be in based on the activities running in it, listed here
in order of importance. The system will kill less important processes
(the last ones) before it resorts to killing more important processes
(the first ones).
The foreground activity (the activity at the top of the screen that the user is currently interacting with) is considered the most
important. Its process will only be killed as a last resort, if it
uses more memory than is available on the device. Generally at this
point the device has reached a memory paging state, so this is
required in order to keep the user interface responsive.
A visible activity (an activity that is visible to the user but not in the foreground, such as one sitting behind a foreground
dialog) is considered extremely important and will not be killed
unless that is required to keep the foreground activity running.
A background activity (an activity that is not visible to the user and has been paused) is no longer critical, so the system may
safely kill its process to reclaim memory for other foreground or
visible processes. If its process needs to be killed, when the user
navigates back to the activity (making it visible on the screen
again), its onCreate(Bundle) method will be called with the
savedInstanceState it had previously supplied in
onSaveInstanceState(Bundle) so that it can restart itself in the same
state as the user last left it.
An empty process is one hosting no activities or other application components (such as Service or BroadcastReceiver classes).
These are killed very quickly by the system as memory becomes low. For
this reason, any background operation you do outside of an activity
must be executed in the context of an activity BroadcastReceiver or
Service to ensure that the system knows it needs to keep your process
around.
Sometimes an Activity may need to do a long-running operation that
exists independently of the activity lifecycle itself. An example may
be a camera application that allows you to upload a picture to a web
site. The upload may take a long time, and the application should
allow the user to leave the application will it is executing. To
accomplish this, your Activity should start a Service in which the
upload takes place. This allows the system to properly prioritize your
process (considering it to be more important than other non-visible
applications) for the duration of the upload, independent of whether
the original activity is paused, stopped, or finished.
Right now I have a server running on a desktop. I want to be able to start up my app, hit a button to start collecting data from this server, and only stop once I hit to button again. The user should always be grabbing data from this server after hitting the button, even if the app isn't active. So far I've considered setting up a Service or using Threads by themself.
A Service sounds exactly like what I need, but I've been told it isn't meant to sustain a long network connection. I poked through the BluetoothChat sample application and it didn't use a Service. Would a Service be the right thing to use then, or should I implement it with threads like the sample application does? The only reason I need a long connection is to listen for any error reports from the server. The other network stuff only happens when the user is directly using the app. I will have to use threads anyways because a Service runs in the same thread as the activity that calls it, but I guess my main question is whether I should scrap the Service part. Right now I have a basic Service set up that can handle messages sent to it and it seems really easy to use. The documentation on it is just all over the place, there needs to be a section saying "If you want to do X, then this is suggested!"
A Service runs on the UI thread, but an IntentService runs in its own thread.
It's ambiguous to say that the "app" isn't active. If you're running a Service, it's always active. An IntentService is active as long as it has finished the work in its onHandleIntent() method. None of the activities of the app may be active, which means that the app is in the background.
Other than that, I'd need to know more about what you're trying to do. In general, it's better to collect data in cycles rather than trying to keep the connection open constantly. For example, what do you do when the device loses connection to the Internet?