Service is off when screen is turns off - android

I am confused a little bit on the behavior of the service.I created a service class which is Emailing my location as soon as the latitude and longitude of My Device is changed.The Service is working perfect when the screen of my phone is on but as soon as the phone screen off the service is not updating me for new locations.I have read somewhere on the SO about wake lock.I don't know how can I implement wake lock on my service and even I don't know whether it will work or not.Please guide me how can I acquire wake lock on my service class
Code for my service class:
public class LocationUpdater extends Service {
private LocationManager lm;
private LocationListener locationListener;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplicationContext(), "Location updater started",Toast.LENGTH_LONG).show();
locationListener = new MyLocationListener();
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0,0,
locationListener);
} else {
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,0, 0,
locationListener);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0, 0,
locationListener);
}
return START_STICKY;
}
#Override
public void onDestroy() {
lm.removeUpdates(locationListener);
super.onDestroy();
}
#Override
public void onCreate() {
Toast.maketext(getApplicationContext,"Updater Serive Created",Toast.LENGTH_LONG).show;
}
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
if (loc != null) {
String latitude=loc.getLatitude();
Striing longitude=loc.getLongitude();
emailMyLocation(latitude,longitude);
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
}
This is the service class which is updating the location of my device to my email.Please tell how can I make it work even if the screen is off.

You should check out answer for this question in the following thread: How can I keep my Android service running when the screen is turned off?. Probably, you need a partial WakeLock, which will keep CPU running even when the screen is turned off. You should also check documentation of PowerManager in Android API, which explains behavior of wake locks.

You can aquire the wake lock like this:
Make a Globals class and declare wakelock as static variable
public class Globals {
public static PowerManager.WakeLock wakelock;
}
Now in your service class Declare these:
PowerManager.WakeLock wakeLock ;
PowerManager pm;
Now you can have two functions for wakelocks:
public void acquirewakeLock() {
if(Globals.wakelock!=null){
Globals.wakelock.release();
Globals.wakelock=null;
}
pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"TrackerService");
wakeLock.acquire();
Globals.wakelock=this.wakeLock;
}
public void releaseWakelock() {
wakeLock.release();
}
Now in your onCreate method you can quire wakelock with this:
#Override
public void onCreate() {
acquirewakeLock()
}
This will take care of whether CPU is held by other activities and services or not.And you will be able to give cpu to your sevice class.
You can also use
wakelock.acquire(time in milliseconds)
if you know the time your service needs to process. :)

Related

GPS Service stops after push power button

I'm starting a GPS location service on several devices, the service works correctly in devices with Android Version <= 7 even when the power button is pressed and in the lockscreen status, but I tried in a Nokia 3 with Android 8.0.0 and the service stops after push the power button but it doesn't stop when the device locks by itself after some time. When I push the power button and unlock the device the service starts to send the GPS data again. This is my code:
public class GPS_Service extends Service {
private static final String TAG = GPS_Service.class.getName();
private static final int minTimeSecondsSamplingRate = AppConfig.GPS_MIN_TIME;
private static final int minDistMetersSamplingRate = AppConfig.GPS_MIN_DISTANCE;
private LocationManager locationManager;
private LocationListener locationListener;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#SuppressLint("MissingPermission")
#Override
public void onCreate() {
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Location changed");
Intent intentSendToMainActivity = new Intent(AppConfig.C_STR_INTENT_FILTER_LOCATION_CHANGED);
intentSendToMainActivity.putExtra(AppConfig.C_STR_LATITUDE, location.getLatitude());
intentSendToMainActivity.putExtra(AppConfig.C_STR_LONGITUDE, location.getLongitude());
sendBroadcast(intentSendToMainActivity);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
if (locationManager != null) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTimeSecondsSamplingRate, minDistMetersSamplingRate, locationListener);
Log.i(TAG, "Starting Location Service");
} else {
Log.e(TAG, "Can't Start Location Service");
}
}
#Override
public void onDestroy() {
super.onDestroy();
if (locationManager != null) {
locationManager.removeUpdates(locationListener);
}
}
}
I've tried dissabling the battery optimization for my application but the problem persists
stop/start location update if no location is received in 2 minutes
also create a service an make it foreground and put location updates methods inside it
all the best

RequestLocationUpdates Time of life

RequestLocationUpdates is a method of LocationManager, receives GPS information periodically.
I think if I send from onCreate application should not be a problem because it will not overcharge the main thread, I'm right?
If I want to receive information requestLocationUpdates, even after the application closed, from where should I send it?
I think for the most part you will want to register a BroadcastReceiver. one of the broadcasts that you can watch for is when the location changes. There are a few logistical concerns with this such as how to interact with the BroadcastReceiver and how much battery your application will consume. A good summary of how to address these concerns can be found here.
Essentially you will want to make an Intent (your specific way of identfying an event you're looking for has happened) and a PendingIntent(A way to make that event interact with LocationServices).
PendingIntent launchIntent = PendingIntent.getBroadcast(context, 0, myIntent, 0);
manager.requestLocationUpdates(provider, minTime, minDistance, launchIntent);
In the end the best solution I found was to use Service, as follows:
public class GpsService extends Service implements LocationListener{
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
LocationManager LocManager =(LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
LocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, this);
return Service.START_STICKY;
}
public void onLocationChanged(Location location) {
Log.i("location", String.valueOf(location.getLongitude()));
Log.i("location", String.valueOf(location.getLatitude()));
}
public void onProviderDisabled(String provider) {
Log.i("info", "Provider OFF");
}
public void onProviderEnabled(String provider) {
Log.i("info", "Provider ON");
}
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.i("LocAndroid", "Provider Status: " + status);
Log.i("info", "Provider Status: " + status);
}
}
And in onCreate () I launch the service:
public class PacienteApp extends Application {
#Override
public void onCreate() {
Intent intent = new Intent(this, GpsService.class);
this.startService(intent);
}
}
Using Broadcast Receiver is a good idea, but laborious as they are not allowed to use handlers within this class. And anyway you need the service to run in the background.

How to separate location listener and Google map

I am trying to make a location tracking application on an android phone, it will be just same as the built-in google map in the phone. It will continue to track the phone even the app is close, so it will be running in the background of other applications.
I am thinking of splitting up both the classes, User Interface (Google Map) and location tracking, where the location tracking will always run but the google map will only display when the user open the application. Thus this is what I reached so far.
MapDisplay class for Google Map
public class MapDisplay extends Activity {
private GoogleMap map;
private LocationService locationService;
private Intent locationServiceIntent;
private Location myLocation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_display);
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.googleMap)).getMap();
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
map.setMyLocationEnabled(true);
locationServiceIntent = new Intent(this, LocationService.class);
x=0;
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
startService(locationServiceIntent);
bindService(locationServiceIntent, locationServiceConnection, Context.BIND_AUTO_CREATE);
}
#Override
public void updateLocation()
{
// for testing purpose, to make sure it will update periodically
Toast.makeText(MapDisplay.this, String.valueOf(myLocation.getLatitude()), Toast.LENGTH_SHORT).show();
}
private ServiceConnection locationServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
locationService = ((LocationService.LocationBinder)service).getService();
myLocation = locationService.getMyLocation();
updateLocation();
}
#Override
public void onServiceDisconnected(ComponentName name) {
locationService = null;
}
};
}
LocationService class
public class LocationService extends Service implements LocationListener
{
private LocationManager locationManager;
private Location myLocation;
private IBinder locationBinder = new LocationBinder();
public class LocationBinder extends Binder
{
public LocationService getService()
{
return LocationService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return locationBinder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
myLocation = null;
boolean networkProviderAvailable = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
boolean gpsProviderAvailable = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if(networkProviderAvailable)
{
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
}
else if(gpsProviderAvailable)
{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
else
{
stopSelf();
}
return super.onStartCommand(intent, flags, startId);
}
public Location getMyLocation()
{
return myLocation;
}
#Override
public void onLocationChanged(Location location) {
myLocation = location;
}
#Override
public void onProviderDisabled(String arg0) {
}
#Override
public void onProviderEnabled(String arg0) {
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
}
Using code above I experienced application crash because of this line
myLocation = locationService.getMyLocation();
String.valueOf(myLocation.getLatitude())
It can't get the location from LocationService class.
So, my questions are:
1) is this a good way to make the application?
2) how to periodically call the updateLocation() in MapDisplay when there are new updates in onLocationChanged method?
I will be much appreciate if someone can help me on this.
You have to account for the case that you have not yet received a location. To do that, your client code needs to check the return of getLocation for null, and handle accordingly.
Additionally you may want some more intelligence in onLocationChanged. Right now if a gps location comes in and then a network location comes in, the network location will overwrite the gps location, despite being less accurate. I'd take a look at some code I wrote at http://gabesechansoftware.com/location-tracking/ You'll see a class FallbackLocationTracker which will track both gps and network location, returning the most accurate location received so far. I think it does what you're trying to do.

Stopping a LocationListener Service

I want to stop LocationListener, but using a Log, I´ve found out that my service is still running after removeUpdates() method (When the location changes, it´s inserted into my log). Do you know where the problem is? Thanks in advance.
public class MyService extends Service implements LocationListener {
private final static String TAG = "MyService";
LocationManager lm;
public MyService() {
}
....//Other methods here
public void onLocationChanged(Location loc) {
Log.d(TAG, loc.toString());
if(/*A condition, which has to stop the service when it´s time*/)
{
lm.removeUpdates(this);
lm = null;
}
}
public void subscribeToLocationUpdates() {
this.lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
this.lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
#Override
public void onDestroy() {
}
}
I call this service in another Activity, onCreate method:
ComponentName comp = new ComponentName(getPackageName(),
MyService.class.getName());
ComponentName service = startService(new Intent().setComponent(comp));
The Service object and its lifecycle is independent of the state of your location manager. or any other object for that matter.
A service represents a background part of your app. once you are done with it you can call finish() method to end it.
So in your case :
public void onLocationChanged(Location loc) {
Log.d(TAG, loc.toString());
if(/*A condition, which has to stop the service when it´s time*/)
{
lm.removeUpdates(this);
lm = null;
stopSelf(); // end this service
}
}
Please take a look at android's Service documentation to get a general overview of its nature : Android Service

How do I keep the Thread of an IntentService alive?

I'm writing a test application which keeps track of the users location. The idea is that i can start a service which then registers for location updates. For now I'm using an IntentService for that.
The service code (which is not working...) looks like that:
public class GpsGatheringService extends IntentService {
// vars
private static final String TAG = "GpsGatheringService";
private boolean stopThread;
// constructors
public GpsGatheringService() {
super("GpsGatheringServiceThread");
stopThread = false;
}
// methods
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand()");
return super.onStartCommand(intent, flags, startId);
}
#Override
protected void onHandleIntent(Intent arg0) {
// this is running in a dedicated thread
Log.d(TAG, "onHandleIntent()");
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
LocationListener locationListener = new LocationListener() {
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "onStatusChanged()");
}
#Override
public void onProviderEnabled(String provider) {
Log.d(TAG, "onProviderEnabled()");
}
#Override
public void onProviderDisabled(String provider) {
Log.d(TAG, "onProviderDisabled()");
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged()");
}
};
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
while (!stopThread) {
try {
Log.d(TAG, "Going to sleep...");
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy()");
stopThread = true;
}
}
Currently the only thing which happens is the output of "Going to sleep...". I need some mechanism which keeps the thread alive (because else the listener is not reachable anymore for status updates) and doesnt waste cpu time (I think busy looping is not the preferred way).
Even if there are tons of other ways how to realize the application behaviour (logging of gps coordinates) I am interested in a solution to this way to learn a technique to solve problems of this nature!
How do I keep the Thread of an IntentService alive?
You don't. You do not use IntentService in a scenario like this.
I need some mechanism which keeps the thread alive (because else the listener is not reachable anymore for status updates) and doesnt waste cpu time (I think busy looping is not the preferred way)
No, in this case a Service is fine, because you control when the service is going away, you control the lifetime of any threads you create, etc. IntentService is unsuitable for your intended purpose, because it controls when the service is going away and it controls the lifetime of the threads.
Consider using a remote service. It worked for me.

Categories

Resources