3

I am trying to build an app that has a service that sends the current location to a server every X minutes.

Looking at other posts in SO, found that the method outlined in commons-ware https://github.com/commonsguy/cwac-wakeful would work best. The demo2 app here works fine for me and it writes a message to Alarm.txt every x minutes.

I did the following modifications to "AppService.java" so that it attempts to get a location instead of what it does as a sample program.

public class AppService extends WakefulIntentService {

private Context context;
    public AppService() {
       super("AppService");
    }

    @Override
    protected void doWakefulWork(Intent intent) {
    //    File log=new File(Environment.getExternalStorageDirectory(),
    //                      "AlarmLog.txt");
    //    
    //    try {
    //      BufferedWriter out=new BufferedWriter(new FileWriter(log.getAbsolutePath(),
    //                                                           log.exists()));
    //      
    //      out.write(new Date().toString());
    //      out.write("\n");
    //      out.close();
    //      Log.e("AppService", "wrote to log file");
    //    }
    //    catch (IOException e) {
    //      Log.e("AppService", "Exception appending to log file", e);
    //    }
      context = this.getApplicationContext();
      Log.e("AppService", "Attaempting to get location");
      new GetLocation(context).execute();
   }
}

My GetLocation.java looks like this

public class GetLocation {

private LocationManager locationManager;
private LocationListener locationListener;
private Context context;

public GetLocation(Context context) {
    this.context = context;
}

public void execute() {
    locationManager = (LocationManager) context
            .getSystemService(Context.LOCATION_SERVICE);
    locationListener = new LocationListener() {

        @Override
        public void onLocationChanged(Location location) {
            new SendLocation2(location).execute();
            locationManager.removeUpdates(locationListener);
        }

        @Override
        public void onProviderDisabled(String provider) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onProviderEnabled(String provider) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onStatusChanged(String provider, int status,
                Bundle extras) {
            // TODO Auto-generated method stub

        }
    };
    Log.e("AppService", "Registered to get location");
    locationManager.requestLocationUpdates(
            LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
}

}

Send location uses apache http client library to upload the location to the server.

When I run this I get the following in the logcat.

06-06 08:06:27.031: E/AppService(3161): Attaempting to get location
06-06 08:06:27.039: E/AppService(3161): Registered to get location


W/MessageQueue(3161): Handler (android.location.LocationManager$ListenerTransport$1)  {41855e68} sending message to a Handler on a dead thread
W/MessageQueue(3161): java.lang.RuntimeException: Handler (android.location.LocationManager$ListenerTransport$1) {41855e68} sending message to a Handler on a dead thread
W/MessageQueue(3161):   at android.os.MessageQueue.enqueueMessage(MessageQueue.java:294)
W/MessageQueue(3161):   at android.os.Handler.enqueueMessage(Handler.java:618)
W/MessageQueue(3161):   at android.os.Handler.sendMessageAtTime(Handler.java:587)
W/MessageQueue(3161):   at android.os.Handler.sendMessageDelayed(Handler.java:558)
W/MessageQueue(3161):   at android.os.Handler.sendMessage(Handler.java:495)
W/MessageQueue(3161):   at android.location.LocationManager$ListenerTransport.onLocationChanged(LocationManager.java:218)
W/MessageQueue(3161):   at android.location.ILocationListener$Stub.onTransact(ILocationListener.java:58)
W/MessageQueue(3161):   at android.os.Binder.execTransact(Binder.java:351)
W/MessageQueue(3161):   at dalvik.system.NativeStart.run(Native Method)

I looks like the app does not stay alive till its callback onLocationChanged() is called by the location manager. How can I fix this?

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
Harkish
  • 2,262
  • 3
  • 22
  • 31

1 Answers1

1

Looking at other posts in SO, found that the method outlined in commons-ware https://github.com/commonsguy/cwac-wakeful would work best.

Absolutely not. An IntentService of any form is inappropriate for your use case. An IntentService cannot register listeners, fork its own threads, or do anything that will continue running past the end of onHandleIntent(). Once onHandleIntent() returns, the service will shut down if there are no further commands to process, and that in turn can lead to your process being terminated.

For cases where you need to register a listener, use a regular Service, with your own managed WakeLock, where you control when the service shuts down.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Hi CommonsWare, the LocationPoller link is dead 404. Have you removed the LocationPoller Project ? If Not then kindly tell me the correct link, if yes then is there an alternative for location polling ? Having same situation as OP. – Sharp Edge Nov 30 '16 at 01:09
  • @SharpEdge: "Have you removed the LocationPoller Project ?" -- yes. Thanks for pointing it out; I have removed that link from the answer. "is there an alternative for location polling ?" -- I haven't looked for one. – CommonsWare Nov 30 '16 at 01:13
  • "For cases where you need to register a listener, use a regular Service, with your own managed WakeLock, where you control when the service shuts down" So can I just modify your [Wakeful](https://github.com/commonsguy/cwac-wakeful) and replace `IntentService` with a regular `Service` handling its disposal and time outs etc ? – Sharp Edge Nov 30 '16 at 01:18
  • 1
    @SharpEdge: `WakefulIntentService` is optimized for a different scenario. It would not make for a good starting point, though it is possible that it will give you some implementation ideas. – CommonsWare Nov 30 '16 at 01:20
  • Could you at least point me to right direction ? I need to send location to server every 15 minutes even if the app is closed. My guess is that if the device is sleeping the service won't be called neither will the alarm manager in some cases. Any pointers will be appreciated. – Sharp Edge Nov 30 '16 at 01:23
  • @SharpEdge: "Could you at least point me to right direction ?" -- as I wrote, and as you quoted: use a regular `Service`, with your own managed `WakeLock`, where you control when the service shuts down. "I need to send location to server every 15 minutes even if the app is closed" -- use `JobScheduler`, `AlarmManager`, etc. to attempt to trigger this. "My guess is that if the device is sleeping the service won't be called neither will the alarm manager in some cases" -- correct. – CommonsWare Nov 30 '16 at 01:27
  • "And there is nothing that you can do about this" Well a service running all the time with STICKY will be an attempt. Thanks – Sharp Edge Nov 30 '16 at 01:29