3

I have created a sample foreground service to check if it's possible to fetch location from background after every 15 mins or 30 mins. With introduction to doze mode alarm manager does not work at exact time.

In foreground service I have tried using handler post delay but that also does not work as I am getting intervals of upto 3 hrs. In the below code I have used ScheduledThreadPoolExecutor and it performed even worse. I got delay of upto 12 hours. I have tested this on android 6.0 as of now.

Can anyone suggest a work around for this?

package com.hitec16.foregroundservicetest;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

import java.text.DateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MyService extends Service
        implements LocationListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    private static final String TAG = "MyService";
    private static final long INTERVAL = 1000 * 10;
    private static final long FASTEST_INTERVAL = 1000 * 5;
    private static final long WAIT_INTERVAL = 1000 * 30;

    private ScheduledThreadPoolExecutor mExecutor;

    private int mCounter = 0;

    private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;
    Location mCurrentLocation;
    private String mLastUpdateTime;

    public MyService() {
    }


    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
//        throw new UnsupportedOperationException("Not yet implemented");
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(final Intent intent, final int flags, final int startId) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                onStart_(intent, flags, startId);
                Looper.loop();
            }
        });
        thread.start();
//        onStart_(intent,flags,startId);

        return START_STICKY;
    }

    private void onStart_(Intent intent, int flags, int startId) {
        if (intent.getAction().equals(Constants.STARTFOREGROUND_ACTION)) {
            Logger.d("Received Start Foreground Intent ");

            createLocationRequest();
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();

            connectToGoogleApi();
            showNotification();
            Toast.makeText(getApplicationContext(), "Service Started!", Toast.LENGTH_SHORT).show();
            Logger.d("work finished");

//            fetchLocationAgain();
            mExecutor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(2);
            mExecutor.scheduleWithFixedDelay(new Runnable() {
                @Override
                public void run() {

                    try {

                        startLocationUpdates();
                    } catch (Exception e) {
                        Log.d(getClass().getSimpleName(), "Exception caught: " + e.getMessage());
                    }
                    Log.d("Test", "test");
                }
            }, 30, 60 * 15, TimeUnit.SECONDS);
        }
    }

    private void showNotification() {
        Intent notificationIntent = new Intent(this, MainActivity.class);
        notificationIntent.setAction(Constants.MAIN_ACTION);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                notificationIntent, 0);

        Notification notification = new NotificationCompat.Builder(this)
                .setContentTitle("Fused Location Service")
                .setTicker("ticker text")
                .setContentText("My Location")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(pendingIntent)
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .build();

        startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE,
                notification);
    }

    protected void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    protected void stopLocationUpdates() {
        LocationServices.FusedLocationApi.removeLocationUpdates(
                mGoogleApiClient, MyService.this);
        mCounter = 0;
        Logger.d("Location update stopped .......................");
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Logger.d("onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
        try {
            startLocationUpdates();
        } catch (Exception e) {
            Log.d(getClass().getSimpleName(), "Exception caught: " + e.getMessage());
        }
    }

    @Override
    public void onConnectionSuspended(int i) {    
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Logger.d("Connection failed: " + connectionResult.toString());
    }

    @Override
    public void onLocationChanged(Location location) {
        if (mCounter < 3) {
            Log.d(getClass().getSimpleName(), "returned....");
            mCounter++;
            return;
        }
        Logger.d("Firing onLocationChanged..............................................");
        mCurrentLocation = location;
        mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());

        Logger.d("Location latitude and longitude :" + location.getLatitude() + " ," + location.getLongitude()
                + " , Accuracy : " + location.getAccuracy() + ", location provider : " + location.getProvider() + "Time : " + mLastUpdateTime);

        stopLocationUpdates();
    }

    protected void startLocationUpdates() throws Exception {
        PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
                mGoogleApiClient, mLocationRequest, this, Looper.getMainLooper());
        Logger.d("Location update started ..............: ");
    }

    @Override
    public void onDestroy() {
        disconnectFromGoogleApi();
        Log.d(getClass().getSimpleName(), "on destroy called");
        mExecutor.shutdown();
        super.onDestroy();
    }

    private void connectToGoogleApi() {
        Logger.d("connectToGoogleApi fired ..............");
        mGoogleApiClient.connect();
    }

    private void disconnectFromGoogleApi() {
        Logger.d("disConnectFromGoogleApi fired ..............");
        mGoogleApiClient.disconnect();
    }
}
Aaron
  • 7,000
  • 2
  • 21
  • 37
Hitesh Bisht
  • 486
  • 1
  • 6
  • 11

0 Answers0