My main requirement would be to have a service having its own process and trigger its own geofencing event. I'd like the user to be notified from the notification center when he enters a geofence, even if the app is killed.
I read about services and this seems pretty clear to me, the Android documentation is dense so I managed to understand how to start a service with its own process, and also how it is able to communicate with the app using Messenger.
Then there is this code sample from Google showing how to use geofencing with google play services:
Google samples geofencing
What I found so far is that we have to use an IntentService to trigger geofencing events, and from the docs I've read it states that an IntentService terminates itself when its work is done. And I tested a bit also, it looks like the Intentservice gets killed when the app gets killed, which doesn't surprise me regarding the documentation.
So my question is, how could we perform a geofencing service having its own process? Is that possible to avoid using IntentService for this matter?
EDIT:
The reason I wanna do this, is that the user can set geofence "reminders", it is based on a daily usage. For instance imagine each day you arrive at your workplace, we should be able to fire an alarm (or a notification) when we enter this geofence regarding the app is running or not. We don't want the user to worry about having the app running in background.
I actually realized this by creating a service with its own process. This service is bound with IPC communication, my activity then registers to it when needed.
Within this service, I did apply the geofencing example that I found in google samples. It uses an IntentService to trigger geofencing events. Instead of using this logic in my activity, I use it in my own service. Now I can receive notifications even when my app is killed.
You don't have to use separate process for this purpose (unless you have other features in mind which you didn't say here loud)
Use WakefulBroadcastReceiver which is indeed perfect for handling geofence transition events.
You are right about Intentservice ,It gets killed as it completes its task.
But there is a work around that can get you service working even after your app is killed.
Do remove following code from you Activity where you mentioned location code.
Remove mentioned code from you activity
check your onPause()
#Override
protected void onPause() {
super.onPause();
//Comment out below code
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
check your code in onStop()
#Override
protected void onStop() {
super.onStop();
//Comment out the below code if you have done in your activity to disconnect from google api client.
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
Put some log in your Intentservice ,You will see that when you run your app after mentioned modification you can even get location update even after you app is killed. :-)
Related
I know that there are a few reasons why android OS may kill a running foreground service. It can be a battery issue, a memory issue, or simply the user killed it by force. Not sure if there are other issues too.
Now I would like to know the reason for the kill from a callback and send it to firebase analytics for making some statistics. The foreground service that I am using sends two HTTP requests every 15sec. I know there are other ways to do this. but right now i am stuck with this code anyway.
In my research, I have found a call-back method.
public void onTaskRemoved(Intent rootIntent) {
}
This is called if the service is currently running and the user has
removed a task that comes from the service's application. If you have
set ServiceInfo.FLAG_STOP_WITH_TASK then you will not receive this
callback; instead, the service will simply be stopped.
As it says this callback only works when the user will remove the task. But what about the memory or battery issue, or other issues if there are any?
I will really appreciate any help here.
Thanks, everyone.
I'm working on an app with GEOfencing API. I have created a geofence and whenever a user leaves already specified geofence, broadcast receiver is triggered and I can successfully display a log message. However when my application is in the background, onReceive method of Broadcast Receiver is not triggered, even though Geofencing is working, my onReceive method will be triggered only when I open the app in foreground. How can this be achieved in the background?
You can use WorkManager to schedule tasks.
WorkManager is an API that makes it easy to schedule deferrable, asynchronous tasks that are expected to run even if the app exits or the device restarts. The WorkManager API is a suitable and recommended replacement for all previous Android background scheduling APIs, including FirebaseJobDispatcher, GcmNetworkManager, and Job Scheduler.
The broadcast listener can also be triggered when the app is in background.
Check out the link for implementation of WorkManager with AlarmManager, you will get a rough idea of how the whole thing works.
Click here
I figured it out.
The problem with was with Android Emulator. I didn't receive a Log message from my Broadcast receiver when I triggered the geofence (When my app was in background), because there is a BUG in Android Emulator. You need to have Google Maps Application opened to receive a trigger from geofence from your app in the background.
It's a strange bug, and it took me few days of debugging to figure it out.
I have an Android app that connects to surrounding devices currently running the same app, even if in background.
To do this, I use WiF-Direct to advertise the fact that I am currently running said application.
Therefore I need to stop advertising this as soon as the app is killed.
onDestroy() cannot be used since it is not guaranteed to be called.
onStop() and onPause() cannot be used since the app is still running.
How can I achieve this?
Currently the service is still being advertised even when the application is closed/killed.
You should be able to do this with a Service.
Start a service when your app was started.
Override the onTaskRemoved method
#Override
public void onTaskRemoved(Intent rootIntent)
{
}
In this method do what you have to do.
More detailed answer can be found here: How to know when my app has been killed? (2 answer)
The best implementation might be to have another service running that queries the your app is in foreground(i.e. running)
You can run the query to check periodically say every 60 sec. Then if the app isn't running. You can stop the WiFi Direct service and subsequently stop self.
I have an Android app that connects to surrounding devices currently running the same app, even if in background.
To do this, I use WiF-Direct to advertise the fact that I am currently running said application.
Therefore I need to stop advertising this as soon as the app is killed.
onDestroy() cannot be used since it is not guaranteed to be called.
onStop() and onPause() cannot be used since the app is still running.
How can I achieve this?
Currently the service is still being advertised even when the application is closed/killed.
You should be able to do this with a Service.
Start a service when your app was started.
Override the onTaskRemoved method
#Override
public void onTaskRemoved(Intent rootIntent)
{
}
In this method do what you have to do.
More detailed answer can be found here: How to know when my app has been killed? (2 answer)
The best implementation might be to have another service running that queries the your app is in foreground(i.e. running)
You can run the query to check periodically say every 60 sec. Then if the app isn't running. You can stop the WiFi Direct service and subsequently stop self.
I have a confusion between Service and BroadcastReceiver. I am working on a Location-based app. In this, I want to store user's location into database whenever there is a significant change in his/her location(eg. 10 meters).
I am using LocationListener for it and it is working fine. But my dilemma is : where to write the onLocationChanged() method - In the onReceive() method of BroadcastReceiver or in a Service?
And if I am using a Service, then in which method of Service , shall I write the below code?
Here is my Location Listener:
LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
if(location != null){
//Code to populate location-data into the database table.
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5, 10, locationListener);
Can anyone please suggest me what is the better way to implement it? I have read all the Android Developer Docs about both Service and BroadcastReceiver , but I am still not able to differentiate between their usage?
It depends on your purpose. If you want to catch the location in the background, use in Service.
BroadcastReciever's onReceive method will call only when what action you registered to receive.
If you want to do in Foreground, you can simply use it in the Activity. But when your activity is closed, you can't get the locations.
So, you decide according to your functionality.
Services are used to run your code in background, are used mainly to download, music play.. after the user puts the app in background(presses home or back button).
BroadcastReceivers are used to receive messages sent through sendBroadcast() method and are used to catch system notifications like Bluetooth, internet availability, get messages from other apps...
I think you want to use Services here because BroadcastReceiver can't help you to listen a location change if the app is in background.
In my opinion, it depends on how much work you want to do.
If you want to do something small when you receive a broadcast, then you can do it in onReceive() method of your BroadcastReceiver. BUT, onReceive() is called on the main application thread. So, Android OS will kill it if it takes too long.
Thus, if you want to do something that might take a while, you should do it in Service on a background thread. As it was suggested, you can put your code in the service's onStart() method. Don't keep the service running if it does not do anything (waist of battery and other resources). Start service every time you receive a broadcast and finish it as soon as it has completed the assigned job.
P.S. Mark L. Murphy (aka CommonsWare) has several excellent books about Android development. Google Busy Coder's Guide Android Development.
UPDATE:
About your desire to cancel your background task when your applications goes to background.
Consider what you will do if your background task is interrupted in the middle. You need to handle this situation. If you are OK with that, then you can use either AsyncTask or Service to do your task in background. Your choice again depends on your task's size and type.
AsyncTask is generally intended to perform background operations and publish results on the UI thread. Android documentation suggests that tasks for AsyncTask should not exceed few seconds. On the other hand, Service is designed to perform long operations without communications with UI.
About canceling. AsyncTask will be canceled when your activity is finished as it is tired to the UI thread. To stop service you will need to call stopService() from your activity.
As you need to store location information frequently, you can start service when you activity starts, communicate with it making use of the service's onBind() method, and then stop your service in the onPause() method of your activity.