2

I have android app,I want to calculate the distance for every two minutes when the user click start button.So I have Service class in my application ,in that class I have googleapiclient.

So I'm getting location for every two minutes I'm adding that distance in sharedpreference but mobile goes to sleep mode means ,distance is not calculating when user click ends button .

I think service get stopped.Please help me to fix my issue. What I have to do when mobile goes to sleep mode,If i calculate distance in activity page means when application is in background distance wont calculate, that's why I'm adding distance in service.

Code:

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

    LocationManager locationManager ;
    SharedPreferences sharedPreferences,startdistance_preference;
    SharedPreferences.Editor editor;
    Timer timer;
    String networkinformation;
    MyLocationService.MyTimerTask myTask;
    String gs_var_userid,gs_var_usetoken;
    private GoogleApiClient mGoogleApiClient = null;
    Double mlastlocationlat,mlastlocationlong,mcurrentlocationlat,mcurrentlocationlong;

    private static final LocationRequest REQUEST = LocationRequest.create()
            .setInterval(10000)
            .setFastestInterval(10000)
            .setSmallestDisplacement(0)
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    public static boolean isGPSEnabled = false;
    public static boolean isNetworkEnabled = false;
    String strlevel;
    SimpleDateFormat simpledateformat;
    String Date;
    int deviceStatus;
    String currentBatteryStatus="Battery Info";
    private final int UPDATE_INTERVAL = 10000; // 5 sec
    private final int FASTEST_INTERVAL = 10000; // 1 sec
    private final int DISPLACEMENT = 0; // 10 meters

    LocationRequest mLocationRequest;
    public void createLocationRequest() {
        mLocationRequest = LocationRequest.create();
        mLocationRequest.setInterval(UPDATE_INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
    }
    String provider;
    double f_TotDist ;
    //to check gps is enabled or not
    @Override
    public void onCreate() {
        super.onCreate();
       Log.i("FG","oncreate");

        locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);
        isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

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


        mGoogleApiClient.connect();

    createLocationRequest();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
 return START_STICKY;
    }
    @Override
    public void onLowMemory() {
        super.onLowMemory();

    }

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

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("DF","ondestroy");
       // mGoogleApiClient.disconnect();
     // LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
    }



    private synchronized void buildGoogleApiClient() {
        try {
            mGoogleApiClient = new GoogleApiClient.Builder(getApplicationContext())
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
            mGoogleApiClient.connect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }







    @Override
    public void onConnected(@Nullable Bundle bundle) {
        try {

            Log.i("FG","----onConnected----service1");
            if (ActivityCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

                return;
            }
            if (mGoogleApiClient != null) {
                mGoogleApiClient.connect();

                mGoogleApiClient.connect();
                LocationServices.FusedLocationApi.requestLocationUpdates(
                        mGoogleApiClient,
                        REQUEST,
                        this);  // LocationListener


            }
            else
            {
                buildGoogleApiClient();

                LocationServices.FusedLocationApi.requestLocationUpdates(
                        mGoogleApiClient,
                        REQUEST,
                        this);  // LocationListener
            }





        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    // to get current latitude and longitude
    // storing the updated latitde and longitude when user moving and reach destination
    @Override
    public void onLocationChanged(Location location) {
        try {
            Log.i("MS","service class********"+location);

            sharedPreferences = getSharedPreferences("myprefer", MODE_PRIVATE);
            editor = sharedPreferences.edit();
            gs_var_userid=Prefs.getuserid(getApplicationContext());
            gs_var_usetoken=Prefs.getusertokene(getApplicationContext());


            editor.putString("dest_Lat", String.valueOf(location.getLatitude()));
            editor.putString("dest_Long", String.valueOf(location.getLongitude()));

            editor.putString("Lat", String.valueOf(location.getLatitude()));
            editor.putString("Long", String.valueOf(location.getLongitude()));

            startdistance_preference = getSharedPreferences("startLessonPref",
                    Context.MODE_PRIVATE);
                  if(mlastlocationlat==null && mlastlocationlong==null && mcurrentlocationlat==null && mcurrentlocationlong==null)
            {
             mlastlocationlat=location.getLatitude();

                mlastlocationlong=location.getLongitude();

                mcurrentlocationlat=location.getLatitude();

                mcurrentlocationlong=location.getLongitude();



            }
            else
            {
                mlastlocationlat=mcurrentlocationlat;
                mlastlocationlong=mcurrentlocationlong;
                mcurrentlocationlat=location.getLatitude();
                mcurrentlocationlong=location.getLongitude();

            }
            editor.commit();
            Float dist = distanceCal(mlastlocationlat, mlastlocationlong,mcurrentlocationlat, mcurrentlocationlong);




        } catch (Exception e) {
            e.printStackTrace();
        }


    }
    private float distanceCal(double lat1, double lon1, double lat2, double lon2) {


        Location loc1 = new Location("");
        loc1.setLatitude(lat1);
        loc1.setLongitude(lon1);

        Location loc2 = new Location("");
        loc2.setLatitude(lat2);
        loc2.setLongitude(lon2);

        float distanceInMeters = loc1.distanceTo(loc2);

        Log.e("RS--first--","-distanceInMeters-" +distanceInMeters);

        Log.e("RS---#####-1-" + lat1, "--" + lon1);
        Log.e("RS---#####-2-" + lat2, "--" + lon2);

        startdistance_preference = getSharedPreferences("startLessonPref",
                Context.MODE_PRIVATE);
        f_TotDist = startdistance_preference.getFloat("str_TotalDist", 0);
        Log.e("RS","-f_TotDist-first-" +f_TotDist);


        // startLesson_preference = getSharedPreferences("startLessonPref", Context.MODE_PRIVATE);

        f_TotDist+=(distanceInMeters);

        Log.e("RS","-f_TotDist--if-" +f_TotDist);


        SharedPreferences.Editor editor1 = startdistance_preference.edit();


        editor1.putFloat("str_TotalDist", (float) f_TotDist);
        editor1.commit();



        return distanceInMeters;
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

    }

In activity the user when click ends I'm getting distance from service ,but if goes to sleep mode means I didn't get distance,Even I'm printing the distance in activity page using sqlite but when it goes to sleep mode service getting stopped i think.Please help me

2 Answers2

0

It is behaving as per OS design. Starting from Android O, while an app is in the foreground, it can create and run background services freely.

When an app goes into the background, it has a window of few minutes (based on my observations its around 1 - 2 minutes, even less on some other deivces) in which it is still allowed to create and use services. The system stops the app's background services, just as if the app had called the services' Service.stopSelf() methods.

You should avoid running service continuously since it impacts battery life. If you still want to continue the best alternative would be to use ForegroundService. But if System considers your service consume too much processing, then during doze mode this service won't work either.

You can follow this SO which describes how to use ForegroundService.

For location requests, check out this official document. Starting from Android O, there is no way you can request for location update so frequently (every two minutes).

Sagar
  • 23,903
  • 4
  • 62
  • 62
  • even in acitivity page also onlocation changed is not working when it goes to sleep mode – pramila10 radhakrishnan Jun 08 '18 at 05:54
  • @pramila10radhakrishnan app enters background state when OS enters sleep mode. By foreground I mean, user is interacting with your activity – Sagar Jun 08 '18 at 05:55
  • if I use forgroundservice also it will be same problem right?in back – pramila10 radhakrishnan Jun 08 '18 at 06:52
  • @pramila10radhakrishnan Your service won't be terminated immediately. I will run for longer time. However in deep sleep mode, OS might not allow it to function as intended. Check out this [official document](https://developer.android.com/about/versions/oreo/background-location-limits) for location limits – Sagar Jun 08 '18 at 06:54
  • then what is this use.i want to calculate the distance for every two min,upto user end the task.For that purpose what to do,even i use forgroundservice also it will go sleep mode after sometime then what i have to do – pramila10 radhakrishnan Jun 08 '18 at 07:58
  • @pramila10radhakrishnan you don't have much control over it. Android wants to control battery drainage. Requesting location every two minutes is quite battery consuming. Try to use geo fencing instead. – Sagar Jun 08 '18 at 08:05
  • using geo fencing how to calculate the distance for every two mins,for that also we need location right? – pramila10 radhakrishnan Jun 08 '18 at 08:09
  • @pramila10radhakrishnan store your location data. Then when user exits the fence, your app will be triggered. Calculate the distance at that time. As I said, nothing will work continuously. You shouldn't aim for updating distance every 2-minutes, its not realistic. – Sagar Jun 08 '18 at 08:11
  • @pramila10radhakrishnan - Have you got any solution on this issue? – Rasool Mohamed Feb 22 '19 at 02:09
  • This is not a correct answer and not only does it not answer the question properly, it give a personal judgemental and an unsolicited opinion on battery life which is beside the point of the OP. Please stick to responding with proper fact and directly and specifically to the questions asked. –  Dec 11 '20 at 13:44
0

From Android Oreo(API 26) there are serious restrictions in running services in background and location retrievals in background to preserve battery, app may now get location updates couple of times in an hour (no restriction when the app is in foreground)

More details here:

To overcome the restrictions in your location based app, create an BroadCastReceiver which will receive the intent and has logic to handle code specific to your app after you get the location data. Use a pendingIntent to retrieve the Intent when location data is triggered in background as below:

Intent intent = new Intent(this, LocationUpdatesBroadcastReceiver.class);
  intent.setAction(LocationUpdatesBroadcastReceiver.ACTION_PROCESS_UPDATES);
   return PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

Step by step guide provided by google to handle location for oreo: https://codelabs.developers.google.com/codelabs/background-location-updates-android-o/#0

(You may need to look from step 5 more in detail how to handle for oreo)

Psypher
  • 10,717
  • 12
  • 59
  • 83