Service architecture for my app - android

I have an app that traces the location of the phone by using locationlistener to create breadcrumbs. The user can start the app, then start breadcrumb trail recording. The trail shows on a google map in the app live as the trip records. The breadcrumbs are also sent to a clout database where other applications can access the trip being taken.
The user can end the app but choose to keep the breadcrumb recording going so other apps can still follow the trail real time. If the user never comes back to stop recording, the recording will stop 24 hours from the time it started. The user can, however, start the app anytime and stop recording of the trail.
It seems that my app should consist of an activity and a service that the activity binds to. No other app will use this service so it seems the service should not have to be an IPC service. The service does all of the location listening and logging to the cloud database.
My problem is that in the CommonsWare book on page 1226 it says that if my app calls unbindService(), android will shut down the service. I want it to keep going until the activity shuts it down or it shuts itself down after 24 hours.
Does this mean my service must be an IPC service?
How can I end my activity and leave the service running?
Thanks, Gary

First off you want to make your service a foreground service.
Something along the lines of this. (I'd call this code in your services onCreate function.)
Notification notification = new Notification(
R.drawable.ic_dialog_info,
getText(R.string.notification_text),
System.currentTimeMillis());
notification.flags |= Notification.FLAG_AUTO_CANCEL;
Intent activityIntent = new Intent(this, YourMainClass.class);
activityIntent.setAction(Intent.ACTION_MAIN);
activityIntent.addCategory(Intent.CATEGORY_LAUNCHER);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
activityIntent, 0);
notification.setLatestEventInfo(this,
getText(R.string.notification_title),
getText(R.string.notification_text), pendingIntent);
startForeground(123, notification);
Another thing is to not bind your service to your activity. If your activity get's killed you don't want your service to die as well. And if your device get's low on memory, if your activity isn't in the foreground it is a candidate for getting killed. Of course, when memory frees up Android will try to recreate it. But you will have a poor user experience. If your service is not bound to your activity and is foreground, it should be the last thing that gets killed by the OS during garbage collection.
You can start a service without binding it to your activity by using this simple piece of code: This code can be called in your activities onCreate.
Intent service = new Intent(YourContext, YourService.class);
startService(service);
Hopefully this helps you!
Cheers

It seems that my app should consist of an activity and a service that the activity binds to.
Not necessarily. You can use the command pattern for this.
Does this mean my service must be an IPC service?
Not necessarily. You can use the command pattern for this.
How can I end my activity and leave the service running?
Start the service using startService(). Whether it will live for 24 hours is not under your control (see Dyarish's answer for making it be a foreground service, which increases the odds that it will live that long).

Related

How to run a thread in the background after the app is killed

I want to provide the user with toast notifications every 'x' minutes, I tried to do this with the help of service, but when the application was killed, the service stops.
The same issue occurs with intent Service as well, what should I be doing in order for me to keep a thread/service in memory even after the application is killed?
The terms of your question are a bit confusing :
the application lies in a process. If the process is killed, then everything running in that process is killed.
if you want something to survive that process's death, you should use a second process and run the thing to survive inside it.
a service can be run in its own process, looks like a good choice here. Look at android:process attribute in the service tag : http://developer.android.com/guide/topics/manifest/service-element.html
But what you want to do is maybe simpler : set a repeating task. For this, you could use the alarm manager.
You can, for instance :
provide the alarm manager with a pending intent
the pending intent will trigger a service of your own
the service will we waked up, then run. This has the advantage of not letting your service always run and count time to know when it has to wake up (which would drain battery). Here the alarm manager will wake it up when needed, your service will just execute its task and die.
If you combine this approach with the first part of that answer, running your service in a different process, then you can achieve something that's really light weight for the Android device : only your service (in its own process) will wake up at given interval, and the application's process will not be launched by this alarm, but only the service's process.
And about toast notifications, yes, a service is a good place to do it, but the notification bar may be more appropriate to display notifications and notify the user that some event took place inside a background service.
Try implementing foreground service. foreground service
Foreground service displays notification and is never stopped until you want.
Implement this code snippet in your service's onCreate
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

Background Service Stopped When Activity Killed Or Stop or force close

My Problem Is When I M Pressing Home Button And Close My App At That Time Background Service stoped And After That It Requires To LOgin Again In App Then Background Service Will Start So How Can I Do Like Whatssapp If App Will Close Or Kiiled Then Also Sevice Can Run In Background.....
I had the same problem. When you swipe an application out of the application tray, the process of the background service is killed.
You can add the following code in your service or see this question
#Override
public void onTaskRemoved(Intent rootIntent){
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
What this code does is that it restarts the process of your application once it is killed when your activity is killed.
Its very simple, Just follow the scenarios in below link.
Continue Service even if application is cleared from Recent app
your service and processes (Threads run inside your service) will remain continuous.
Ok, I'm just guessing - really don't want to check all code for your application.
Service can be starter in 2 ways:
Using bindService() what probably you are doing here. It's nice, but means that service will be disposed as soon as the last client unbind it (what you probably doing in some onPause() method.
Using the startService() command. In such case service will run as long as you stop it or system will consider that this service is using to much memory that should be used for some more urgent task (ex: some fat activity)
The quick fix for your issue (if my guesses are right) will be switching service to be run in "startService" mode. If you don't want to play much with your code the best place to put it is onBind() method of your service (just try to start service from itself). Of course this will not start the service but will switch it's mode to the "long running, real background one".
This will not solve all your problems as I mentioned above - service still can be killed by system in order to get more resources. You can prevent it in some ways: if you really want to keep service running, you should consider to use foreground service (google it) that will increase chances of the service to survive. But the best option is just to use service lifecycle, save data if needed and load them on service start, just like you should do with activity. For long running background services there is also option start sticky that will cause service starting after every kill, crash etc.

Best architecture for a long running service on Android

I would appreciate some guidance on how to deal with OS killing a long run service.
Business scenario:
Application records a BTT track which may last for several hours. It can also show the track on map together with relevant statistics.
The application user interface enables the user to start/stop track recording and view the real time track on a map.
After start track recording user can exit the application and turn screen off (to save power), and only a service will remain running to keep the recording update to database (notification shown), until the user starts again the activity and ask for stop recording, which results in service termination.
Issue:
After a variable time, which runs from 40 minutes to 1 hour and a half, the recording service gets killed without any warning. As BTT outings may take several hours, this result in track recording incomplete.
Some additional information:
Service is started with START_STICKY and acquires a PARTIAL_WAKE_LOCK, and runs in the same process as the main activity.
New locations are acquired (and recorded) at user defined rate from 1 second to several minutes.
I know from the Android documentation that this is the expected OS behavior for long running services.
Question:
What is the best architecture design approach to have a well behaved application that could satisfy the business scenario requirements?
I can think of a couple of options (and I don’t like any of them), but I would like guidance from someone how have already faced and solved similar issue:
Use broadcast receiver (ideally connected to Location Manager if that’s possible) to have the service only running when a new location
is acquired?
Do not enable the user to leave the main activity (resulting in pour user experience)?
Have an alarm broadcast receiver restarting the service if needed?
Thanks to all who could share some wisdom on this subject.
I have an app that does a very similar thing. I make sure the service keeps running by making it a foreground task. When I am ready to start running, I call this function, which also sets up a notification:
void fg() {
Notification notification = new Notification(R.drawable.logstatus,
"Logging On", System.currentTimeMillis());
Intent notificationIntent = new Intent(this, LoggerActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification.setLatestEventInfo(this, "Logger","Logger Running",
pendingIntent);
startForeground(1, notification);
}
and then to leave foreground mode when logging is finished:
stopForeground(true);

Android: how to get a long running service to start an activity

I need a service to start at boot that periodically checks some database for newly posted data. If there is new data(that fits the correct parameters) I need to then start an activity to display this. I plan on having a notification in-between this to allow the user the choice of dismissing the new data, if they are uninterested or in the middle of some other task. I have some php on a server that I am using to query the database, it works but it is in an activity. I have read a lot on here about alarmManagers and broadcast receivers. I think I need a broadcast receiver that starts on boot, that will start the service that will check for updates, then start the activity if there are.
Thanks a lot
To get a start with broadcast receiver take a look here for example.
Get the service implemented. Take a look at IntentService. It offloads the work into a worker thread, so you don't need to care about that yourself.
Schedule the service to start itself periodically using AlarmManager. Don't forget about wake lock to wake the device if needed.
It is usually not a good idea to start any activities without user consent. Show a notification in the notification bar that some new data is available. When user taps on the notification you start the activity to show the data.
There is more to that you just have to start step by step and make it happen :)
Are you asking how to start the service at boot, or start an activity from the service?
For the later android start activity from service , and for the former Android -Starting Service at Boot Time

Android service killed unexpectedly

I have an Android service that's responsible for firing notifications at certain points in time. I use an android.OS.CountdownTimer for this. An activity creates and starts the service. If the phone is locked, notifications that are within let's say 1min are shown. Notifications that are much later are never shown. The service is unbound from the activity when the activity is onpause.
As long as the phone doesn't lock the notifications are generated, even if the activity is stopped and unbound from the service.
It seems to me that the service is stopped/killed. When I make the application debuggable and debug it on target, it works fine, also when the activity is stopped and the service is unbound.
The app is developed for v1.5 and runs at Galaxy S with 2.2.
Service is started as shown below
serviceIntent = new Intent().setAction("com.mytest.MyService");
startService(serviceIntent);
bindService(new Intent(context,
MyService.class), mConnection, 0 /*Context.BIND_AUTO_CREATE*/);
I have an Android service that's responsible for firing notifications at certain points in time. I use an android.OS.CountdownTimer for this.
Please do not do this. Please use AlarmManager and an IntentService, so you do not have a service running all of the time. Users will kill your service using a task killer or the Manage Services screen in the Settings app. Android will stop your service. You are better served going with an architecture (AlarmManager/IntentService) that works in accordance with user and platform wishes.

Categories

Resources