Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

i want to post location updates every 15mins to server even when the app is not running in the foreground [closed]

I want the location updates to be sent to the server every 15mins to time interval from android phone to the server.Is the service or the alarm manager is the best option.

If i start a service,can i start an asynctask to post locations to the server.?

here is the code i used :

    @Override
    public void onStart(Intent intent, int startId) {
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        listener = new MyLocationListener();
        locationManager.requestLocationUpdates(
                LocationManager.NETWORK_PROVIDER, 4000, 0, listener);
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                4000, 0, listener);
    }




    public class MyLocationListener implements LocationListener {

        public void onLocationChanged(final Location loc) {
            Log.i("**************************************", "Location changed");
            if (isBetterLocation(loc, previousBestLocation)) {
                loc.getLatitude();
                loc.getLongitude();

//              
//              intent.putExtra("Latitude", loc.getLatitude());
//              intent.putExtra("Longitude", loc.getLongitude());
//              intent.putExtra("Provider", loc.getProvider());
//              
//              sendBroadcast(intent);

            }
        }

        public void onProviderDisabled(String provider) {
            Toast.makeText(getApplicationContext(), "Gps Disabled",
                    Toast.LENGTH_SHORT).show();
        }

        public void onProviderEnabled(String provider) {
            Toast.makeText(getApplicationContext(), "Gps Enabled",
                    Toast.LENGTH_SHORT).show();
        }
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

    }
}

I dont know how to run the service background every fifteen minutes of interval.. I want to start an aysnctask when i get fresh location updates.Is the service or the alarm manager is the best option. If i start a service,can i start an asynctask to post locations to the server.?

like image 357
user3035018 Avatar asked Nov 26 '13 07:11

user3035018


People also ask

Which method is best suited for getting location updates?

Permissions. In order to receive location updates from a NETWORK_PROVIDER or GPS_PROVIDER , you must request the user's permission by declaring either the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission, respectively, in your Android manifest file.

Which API is used for continuously obtain the device location?

Using the fused location provider API, your app can request the last known location of the user's device.

How do you check location is on or off in Android?

Settings > Location > Mode > Battery Saving . This mode only uses WiFi, Bluetooth or mobile data instead of GPS to determine the user location. That's why you have to check if the network provider is enabled and locationManager. isProviderEnabled(LocationManager.


1 Answers

Updated answer

Old answer will not work for apps targeting M or higher, because static connectivity receiver will no longer receive broadcasts.

Now, the best option is a FusedLocationApi, which is a part of Google Play Services.

compile 'com.google.android.gms:play-services-location:[version_here]'

Create an IntentService handling location updates

/**
 * Handles location updates from FusedLocationProvider
 */
public final class LocationUpdateService extends IntentService {

    private static final String TAG = "LocationUpdateService";

    public static final String ACTION_HANDLE_LOCATION = "ACTION_HANDLE_LOCATION";

    public LocationUpdateService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(final Intent intent) {
        if (intent != null) {
            final String action = intent.getAction();
            if (action != null) {
                switch (action) {
                    case ACTION_HANDLE_LOCATION:
                        onActionHandleLocation(intent);
                        break;

                    default:
                        Log.w(TAG, "onHandleIntent(), unhandled action: " + action);
                        break;
                }
            }
        }
    }

    private void onActionHandleLocation(@NonNull final Intent intent) {
        if (!LocationResult.hasResult(intent)) {
            Log.w(TAG, "No location result in supplied intent");
            return;
        }

        final LocationResult locationResult = LocationResult.extractResult(intent);
        if (locationResult == null) {
            Log.w(TAG, "LocationResult is null in supplied intent");
            return;
        }

        // TODO send to server using a blocking request.
        // Remember that this is the background thread already
    }
}

Don't forget to add it to Manifest application tag

<service android:name=".LocationUpdateService"/>

Request location permission, connect GoogleApiClient, and you now may do the following

@NonNull
private static PendingIntent createLocationServiceIntent(@NonNull final Context context) {
    final Intent intent = new Intent(context, LocationUpdateService.class);
    intent.setAction(LocationUpdateService.ACTION_HANDLE_LOCATION);

    return PendingIntent.getService(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

public static void scheduleLocationUpdates(@NonNull final Context context,
        @NonNull final GoogleApiClient googleApiClient) {
    // Make sure you have permission, request if necessary
    if (googleApiClient.isConnected() &&
            ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
            // ACCESS_COARSE_LOCATION, depending on what you want
            == PackageManager.PERMISSION_GRANTED) {

        LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient,
                LocationRequest.create().setInterval(AlarmManager.INTERVAL_FIFTEEN_MINUTES),
                createLocationServiceIntent(context));
    }
}

public static void unscheduleLocationUpdates(@NonNull final Context context,
        @NonNull final GoogleApiClient googleApiClient) {
    if (googleApiClient.isConnected()) {
        LocationServices.FusedLocationApi
                .removeLocationUpdates(googleApiClient, createLocationServiceIntent(context));
    }
}

Old answer

AsyncTask is intended for short background operations, mostly when you are waiting in UI. You should better start a Service with WakeLock in this case. But be aware that you will likely drain a battery doing so every 15 minutes. Consider not scheduling Alarms when device is not connected to network.

1) Register a static BroadcastReceiver in Manifest to monitor if device is connected. Intent action for network events in android sdk

2) When device gets connected to the internet and locations are allowed, start a Service that will hold WakeLock, listen for one location update, unregisters location updates, sends location to server, schedules AlarmManager, releases WakeLock and cals stopSelf(); Consider a timeout if location updates are not comming. If timeout reached, unregister location updates, register next Alarm, release WakeLock and call stopSelf.

3) If you receive network disconnected in a Receiver, cancel all Alarms and stop Service if running.

Code sample for step 2 as requested

public final class ConnectivityReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        final PendingIntent wakeupIntent = PendingIntent.getService(context, 0,
                new Intent(context, LocationUpdaterService.class), PendingIntent.FLAG_UPDATE_CURRENT);

        final boolean hasNetwork = !intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
        if (hasNetwork) {
            // start service now for doing once
            context.startService(new Intent(context, LocationUpdaterService.class));

            // schedule service for every 15 minutes
            alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                    SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_FIFTEEN_MINUTES,
                    AlarmManager.INTERVAL_FIFTEEN_MINUTES, wakeupIntent);
        } else {
            alarmManager.cancel(wakeupIntent);
        }
    }

}

public  final class LocationUpdaterService extends Service implements LocationListener {

    private enum State {
        IDLE, WORKING;
    }



    private static State state;

    private LocationManager locationManager;
    private WakeLock wakeLock;

    static {
        state = State.IDLE;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "LocationUpdaterService");
    }


    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (state == State.IDLE) {
            state = State.WORKING;
            this.wakeLock.acquire();
            // register location updates, not gonna code it you know

        }
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        state = State.IDLE;
        if (this.wakeLock.isHeld()) {
            this.wakeLock.release();
        }
    }

    private void sendToServer(Location location) {
        // send to server in background thread. you might want to start AsyncTask here
    }

    private void onSendingFinished() {
        // call this after sending finished to stop the service
        this.stopSelf(); //stopSelf will call onDestroy and the WakeLock releases.
        //Be sure to call this after everything is done (handle exceptions and other stuff) so you release a wakeLock
        //or you will end up draining battery like hell
    }

    @Override
    public void onLocationChanged(Location location) {
        locationManager.removeUpdates(this); // you will want to listen for updates only once
        sendToServer(location);
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

}
like image 87
Yaroslav Mytkalyk Avatar answered Sep 21 '22 01:09

Yaroslav Mytkalyk