I'm developing a similar app to Telegram or WhatsApp, I need to keep a persistent socket connection to a server (I know this is a resource intensive job and I am sure GCM is not going to help in this case, I can't change the architecture at the moment).
First of all I tried writing a Service but since the service is running in the same process as the app's main thread, whenever the app is closed, then the service is restarted. (I have returned START_STICKY on onStartCommand()).
After that I am begining to think I would have to develope an independent service and use AIDL to interact with my app.
I'd appreciate if you could help me with this problem.
Users can always kill your app if they want to. If you've marked your Service as STICKY, Android will simply restart it for you. In this case you will need to recognize that your app has been restarted and recreate the persistent socket connection. There is nothing you can do to prevent a user (or Android) from killing your app under certain conditions.
Related
I tried to find if there's a way to run foreground service (one which would hopefully never be killed) without any ui. (Ok I guess notification is necessary but other than that)
This is a very specific use-case since the device being used is a custom one (not a phone), where we need one 'server' app, and might be couple 'client' apps. Clients app will have all necessary ui, but server app should behave in a way like a web server.
I understand this is not a intention of foreground services, but it is justified in the use-case we have.
Bonus question: Is there a 'best' way to achieve an android process/service absolutely constantly running and never being killed by platform for cleaning the memory, since this service will be de facto critical part of the system. Like a phone/dial app on phones for example
Sorry, I can't write comments so I have to post an answer.
It's not exactly what you are looking for, but maybe this google codelab can help you
start with something:
https://codelabs.developers.google.com/codelabs/while-in-use-location/#0
The code in the sample project starts a foreground service whenever the app leaves foreground, allowing the service to "survive" even if the application it's destroyed. Basically the system will not stop the service because tied to his notification.
Plus the service can be stopped from the notification itself.
Maybe with a foreground service started from a device boot broadcast you can have an "always running service"
I have android application with several services.
This application should send reports to remote server when this application has been started and when has been stopped.
But I don't know how to determine that application was stopped, because application may be stopped (crushed for example), but services still running.
I think that the algorithm should be like this:
Check the mark with last date from storage (and if this mark exists - send "stop" time to the server)
Send "start" message to the server, when application was started
Every 10 minutes application should writes current date and time mark on disk
If I will create service with this check - android can kill this single service when there is low memory, but application can be running. If I will create ScheduledExecutorService in Application class - application can stop, but services can be still running.
Can you help me with solution?
There's really not a single answer to this question. It has been asked many, many times here at SO, but all we can say is it really depends on our app's behavior.
You want to put some Log messages in onPause(), onStop(), onDestroy() in your Activity, and onDestroy() in your Service. Watch the the flow of the app carefully by looking at the Log printed out in the Logcat.
Lots of people try to rely on onDestroy() method because it looks like it is called when the app is completely terminated, but that's not always the case. Sometimes app crashes (force closes) or some people just manually force close it in the app information in settings. In that case, app does not follow the lifecycle of the activities.
One of the suggestions would be creating a thread that runs in background and send a UDP packet to a server saying that the app is alive in every few seconds.
PRO: You don't need to make a handshake with the server so it saves time/resources getting response back from the server.
CON: Thread running background does use battery. UDP can be only used in WiFi environment for recent Android OS.
Hope you find a good way. You may want to comment to your post when you found a good solution, because people would like to know how to solve it, too.
Why not try to trust standard methods Activity?
You should approach onDestroy and / or onPause. It depends on your logic.
In addition, you can try to override Application.onTerminate(). You can read about it (Application) lifecycle here.
I would like to upload large files (~10 - 100Mb wifi or mobile network), but in background, because the user maybe will leave the app and later the system will close the app (if not enoguh memory) I created a service for this case but my problem is that when i killed the app the service restarting and the uploading start again. I found same problems without solution:
keeping background service alive after user exit app
My service is restarted each time the application is closed
So it won't work, but what is the solution? How does the youtube app???
You should use a foreground service via the startForeground() method if you are concerned about the possibility of the service being killed.
From the Service Lifecycle Docs:
A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.)
Do you have control over the server? This seems just like:
Uploading big files over HTTP
Googling brought up a proposal for the Gears project:
https://code.google.com/p/gears/wiki/ResumableHttpRequestsProposal
If you can use a server/plugin/module that will allow for Ranged PUTs, that's your best bet, otherwise you may have to roll-your-own "chunking"... Depending on your tools and knowledge, that may be the best option anyway, you could tweak it to optimize it for your specific mobile conditions.
Currently I believe I'm doing a ok job managing my applications remote service. When I'm done using it I can see the onDestroy() called, perfect...
Now the issue is I can see the remote process still hanging, via DDMS or via phone's running processes. Users see this and think I'm doing stuff on the background etc... blaming my app and than asking for an exit button... Truth is they don't need an exit button!
So my question:
How to gracefully terminate a remote
service process?
I could get the PID and kill it but something tells me this might not be the nice way to do this since the service might be restarted again...
Any help would be greatly apreciated!
-Jona
Currently I believe I'm doing a ok job managing my applications remote service.
Simple solution: get rid of the remote service. If you wrote the app and the service, then you do not need it to be remote. The only time you need it to be remote is if the app and the service are part of two separate apps.
Now the issue is I can see the remote process still hanging, via DDMS or via phone's running processes.
Of course.
How to gracefully terminate a remote service process?
You don't. Android will terminate it if and when it chooses to. Hence, the simple solution is to get rid of the remote service process by not having a remote service in the first place.
I am trying to develop an application which will require a service to
run in the background. I am relatively new to android programming,
and after reading many posts, blogs, how-to's and books on creating
and managing services, I am still pretty confused about which model I
should try to use.
First, let me present (in general) the application requirements: I
need an application which will spawn a background process (service?)
which will connect to a bluetooth device. The bluetooth device is
designed to deliver data to the android device. The issue is that the
data could come in at any moment, so the bluetooth connection has to
stay active. Note that the application is a VERY SPECIFIC app and is
NOT intended for public use. I do understand the arguments for not
having background apps running all the time, but please understand
that this is a very specific application for a very specific client.
Now, in general, I think the program flow would be to start the
application (and launch a UI activity). Then I need to configure and
connect to the bluetooth device. At this point, the user should be
able to do other things - make phone calls, check their email, etc.,
while the bluetooth connection is still active and potentially
receiving data. If data comes in, a notification is fired, etc.
So here are my questions and concerns:
If I start an app (which spawns a UI activity and ultimately my
bluetooth connection service) but the app is killed, apparently, the
service handling the bluetooth connection is killed as well. How can
I keep that alive? I read that Service.setForeground() was
depricated, but even if I were to set it to the foreground, if the app
is killed, the service is killed as well. I need to have it run in
the background with as high of a priority as possible (again, I do
understand that this is considered "bad form", but this is a specific
app and this functionality has been requested by the client).
If I started the app (and the service, etc.), but the user, say,
answers a phone call, the app is put into the background. However,
let's say the user goes back to the home screen and starts a DIFFERENT
instance of the app, i.e., he doesn't hold down the home key to select
the already running app from the task manager but starts a completely
new one. If the service handling the bluetooth connection is still
running, how will this new instance behave? i.e., how can I get it to
connect to the bluetooth service which is ALREADY running in the FIRST
instance of the app instead of this new instance? Do I have to use
some form of a Remote service instead of a local service? This is
where I'm a little confused by things as it seems remote services and
defining an AIDL seems to create a lot of extra overhead, and since
I'm already creating a lot of overhead with the service running in the
background all the time, I want to keep that as small as possible.
How can I insure I am connecting to the same service already running?
1)
The service does not depend on an Activity. You can have it running on the background until you call stopSelf().
You can have a BroadcastReceiver that listens to the android.intent.action.BOOT_COMPLETED so your service is started when the phone is turned on.
2)
Your Activity should bind to the service. And get the info from it.
Check this question.