Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A good example of background service getting location updates #220

Closed
betorobson opened this issue Sep 29, 2016 · 77 comments
Closed

A good example of background service getting location updates #220

betorobson opened this issue Sep 29, 2016 · 77 comments

Comments

@betorobson
Copy link

Please I really need help.

I'm facing a problem here. It is impossible to find A GOOD EXAMPLE of how create a service that must run in background and receive location updates. Also, all examples on developer.android.com are terrible, any one of them really works.

My app aim is get location updates in background, something which looks like so simple but unfortunately I could not find any good example about how to do it.

@veda2vratha
Copy link

Hello

Please try these links once

http://stackoverflow.com/questions/28535703/best-way-to-get-user-gps-location-in-background-in-android

http://stackoverflow.com/questions/8828639/android-get-gps-location-via-a-service

@betorobson
Copy link
Author

betorobson commented Sep 30, 2016

@veda2vratha thank you very much, I have tried these examples that you have sent to me. Actually they are both the same.

Testing it I could see in this example it runs every second requesting a very precisely location. So, I change it to every 20 seconds and 500m for distance which gives me a service running every 20 seconds.

Then I realise that I could be making a mistake about what I'm looking for. The point is, my app does not need a very precisely location in addition, it does not need to run every second ou minute. My app needs only collect relevant location position.

So, what I need indeed is a passive location collector. I've been told that Android OS can broadcast for any app in passive mode location position changes. This is great because reduce battery usage. So, my service location (listener location) will be fired only when Android OS has been request for location by other app for example, Google Maps.

After a few hours looking deep on location providers I found it which is called LocationManager.PASSIVE_PROVIDER. Thats is really cool, looks like exactly what I need.

Here I will share how my service looks like now.

Now, I would like to make a question, why any developer and even on Android Training do NOT talk about LocationManager.PASSIVE_PROVIDER? What is the matter about using it?

I would like to say tank you @veda2vratha again 👍

My Location Service:

package com.example.roberto.trainingbackgroundservice;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.ActivityCompat;
import android.util.Log;

/**
 * Created by roberto on 9/29/16.
 */

public class MyLocationService extends Service {
    private static final String TAG = "MyLocationService";
    private LocationManager mLocationManager = null;
    private static final int LOCATION_INTERVAL = 1000;
    private static final float LOCATION_DISTANCE = 10f;

    private class LocationListener implements android.location.LocationListener {
        Location mLastLocation;

        public LocationListener(String provider) {
            Log.e(TAG, "LocationListener " + provider);
            mLastLocation = new Location(provider);
        }

        @Override
        public void onLocationChanged(Location location) {
            Log.e(TAG, "onLocationChanged: " + location);
            mLastLocation.set(location);
        }

        @Override
        public void onProviderDisabled(String provider) {
            Log.e(TAG, "onProviderDisabled: " + provider);
        }

        @Override
        public void onProviderEnabled(String provider) {
            Log.e(TAG, "onProviderEnabled: " + provider);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            Log.e(TAG, "onStatusChanged: " + provider);
        }
    }

    /*
    LocationListener[] mLocationListeners = new LocationListener[]{
            new LocationListener(LocationManager.GPS_PROVIDER),
            new LocationListener(LocationManager.NETWORK_PROVIDER)
    };
    */

    LocationListener[] mLocationListeners = new LocationListener[]{
            new LocationListener(LocationManager.PASSIVE_PROVIDER)
    };

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }

    @Override
    public void onCreate() {

        Log.e(TAG, "onCreate");

        initializeLocationManager();

        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.PASSIVE_PROVIDER,
                    LOCATION_INTERVAL,
                    LOCATION_DISTANCE,
                    mLocationListeners[0]
            );
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "network provider does not exist, " + ex.getMessage());
        }

        /*try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER,
                    LOCATION_INTERVAL,
                    LOCATION_DISTANCE,
                    mLocationListeners[1]
            );
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "gps provider does not exist " + ex.getMessage());
        }*/
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
        if (mLocationManager != null) {
            for (int i = 0; i < mLocationListeners.length; i++) {
                try {
                    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                        return;
                    }
                    mLocationManager.removeUpdates(mLocationListeners[i]);
                } catch (Exception ex) {
                    Log.i(TAG, "fail to remove location listener, ignore", ex);
                }
            }
        }
    }

    private void initializeLocationManager() {
        Log.e(TAG, "initializeLocationManager - LOCATION_INTERVAL: "+ LOCATION_INTERVAL + " LOCATION_DISTANCE: " + LOCATION_DISTANCE);
        if (mLocationManager == null) {
            mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        }
    }
}

@doyer3112
Copy link

also,i was confused with this problem these days,and found some mobile (maybe the Android Version caused)is ok,some is not work,can't get the location callback (location changed) in background.i have try your written service,didn't work after App switch to background

@vani-chikaraddi-28
Copy link

How can i call in MainActivity?
Can you please help me

@YogeshLegendkiller
Copy link

startservice(new Intent(this,MyLocationService .class));
@vani-chikaraddi

@KingIdee
Copy link

You can try out Google's Locations API...

@vani-chikaraddi-28
Copy link

I want to display longitude and latitude how can i do that. I tried the following code but getting white screen

@OverRide
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged: " + location);
mLastLocation.set(location);
longitude=location.getLongitude();
latitude=location.getLatitude();
Toast.makeText(MyLocationService.this,longitude + "yes" + latitude + " ",Toast.LENGTH_LONG).show();
}

@AndyCr15
Copy link

I have used the code from SO linked above too, but how do I pass the location found back to my app, so I can update location information in Firebase? Thanks!

@Avrahamreiss
Copy link

"but how do I pass the location found back to my app,?" I have created a background app where the user determines how often (in minutes) location services should be activated. It then sends info to SMS, email or both. The easy way (which I use) to transfer data within an app is SharedPreferences. It looks so easy that I was at first sceptical about its use - but it has never failed me.

@AndyCr15
Copy link

Thanks, I found I send it back in a broadcast.

@betorobson
Copy link
Author

@AndyCr15 , definitely one of the easiest way to do that is sending the collected data trough broadcast message. :-)

@gvsharma
Copy link

gvsharma commented Sep 5, 2017

really helpful

@hetang-shah
Copy link

very helpful. Thanks for sharing.

@NancyAndroid
Copy link

Hello

I am developing an app and there is one scenario in which I have to send user location on server every 15 min all is working but sometime current location is incorrect.

I need help to get current accurate location . I have created GPS Tracker - Using GPS provider and Network provider Now the issue is

  • I need location from GPS but when I remove Network provider and use GPS Provider only then Current Latitude & Longitude is 0.0 in Noughat & Marshmallow version.
  • If I used both GPS & Network then it returns wrong sometime .

Please suggest what I have to implement to get current & accurate location in Android app.

@RaziaSandhu
Copy link

You can use

mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
and when it is connected

try {
Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
lat = mLastLocation.getLatitude();
longi = mLastLocation.getLongitude();
} else {
Toast.makeText(getApplicationContext(), "Unable to get Location Check GPS is ON", Toast.LENGTH_LONG).show();
showSettingsAlert();
}
} catch (Exception e) {
e.printStackTrace();
}

@NancyAndroid
Copy link

@RaziaSandhu Hi Thanks for your reply.
I need location without Google play services. This app is for dummy devices for security purpose So there is no play store and play services.

@balireddy
Copy link

Hi,

I am working on Gps to open the plot details if the plot(lat,long)details is matched open the plot details otherwise it show a message , and it working for 5 plots after that if he is not in that plot and the plot is opend .
In other case when i restart the device again it works fine.
this is the problem i am facing can any one help me fast.. i have only one day to submit this work.

this is my location service class pice of code
boolean gpsProviderEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean networkProviderEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (gpsProviderEnabled || networkProviderEnabled) {
            if (networkProviderEnabled) {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE, this);
                if (locationManager != null) {
                    location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                    providerType = "network";
                    Log.d(LOG_TAG, "network lbs provider:" + (location == null ? "null" : String.valueOf(location.getLatitude()) + "," + String.valueOf(location.getLongitude())));
                    updateLocation(location);
                }
            }

            if (gpsProviderEnabled && location == null) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE, this);
                if (locationManager != null) {
                    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                        // TODO: Consider calling
                        //    ActivityCompat#requestPermissions
                        // here to request the missing permissions, and then overriding
                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                        //                                          int[] grantResults)
                        // to handle the case where the user grants the permission. See the documentation
                        // for ActivityCompat#requestPermissions for more details.
                        return;
                    }
                    location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                    providerType = "gps";
                    Log.d(LOG_TAG, "gps lbs provider:" + (location == null ? "null" : String.valueOf(location.getLatitude()) + "," + String.valueOf(location.getLongitude())));
                    updateLocation(location);
                }
            }
        }

@arahant
Copy link

arahant commented Sep 26, 2017

This is exactly I was looking for, thanks. I’m building a custom gps tracker, with plotting my path as my location changes, and plotting an altitude-time graph parallely. This creates too much workload on the main UI thread, and it was skipping frames. This will reduce considerable overload.

@Veer50
Copy link

Veer50 commented Oct 4, 2017

@betorobson and @veda2vratha Thank you so much. I was looking for this everywhere. finally i got the answer from you.

@Veer50
Copy link

Veer50 commented Oct 4, 2017

@toton6868 I am not sure about it will work in this case, but whenever i want to pass data between activities i use Dependancy Injection which is achieved by Dagger.You can inject the instance of this class into another class and get access to the location variable from where you can fetch longitude and latitude(Read about Dagger..). As I am also beginner i don't know how to send location details to server periodically.

@betorobson
Copy link
Author

I'm so glad to help others with my snippet code.
@toton6868 , have you tried a simple?
Here you go a very simple straightforward example that I believe can help you: https://developer.android.com/reference/android/os/AsyncTask.html

@Flul2F
Copy link

Flul2F commented Jan 10, 2018

@veda2vratha , @betorobson

Hello and thanks ! it's working great !

i have a question and post it here 'cause i explored internet since solution.

Let me explain:

I had to send my location to our server (REST API with Express) with a Simply GET +appId (generate Unique ID) + lat + long.
For that i had to retrieve my appId and my token for my request, store in my share preferences.

I used
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this );

I saw a lot of responses about context in services and i already test every solutions, i try in the onCreate / onLocationChanged / onStartCommand but its not recognize my Token or appId .

is there a solution? i'm sorry i'm from the web (html/css/js/php) and i'm juste start learning Java
Life Cycle it's hard for right now

@mehulgohil9957
Copy link

Try this,
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
or Try using name of sharePreference where you stored it by,
SharedPreferences.getSharedPreferences("NAME_HERE",Context.MODE_PRIVATE);

@noman-iu
Copy link

noman-iu commented Apr 9, 2018

OnLocationChange is not running...

@AroundPixels
Copy link

About the topic, 3 good recomendations based on my experience:

  • Use PARTIAL_WAKELOCK to getupdates or do the same action at the same rate when the device is screen off and standby.
  • Best service for this case is Foreground Service. It won't be killed by the system, it is the highest priority server. But you must show the notification widget.
  • Implement a GPS singleton or similar logic with service or application context. Don't rely on any Activity or Fragment to avoid components life cycle.

@betorobson
Copy link
Author

@AroundPixels , The aim of my question in this topic is opposite of your suggestion.
It is pretty common to see implementation of location update running in Foreground Service however, my poporse here is that app listener for those location updates running in passive mode which means less CPU and Battery usage.

For who is looking for a foreground service here it NOT the case.

@betorobson
Copy link
Author

This issue has been solved by the following solution:
#220 (comment)

@AroundPixels
Copy link

Hi @betorobson . I'm only sharing my experience about location services, because I've done several with huge precision requirements. If you need precision, you will need wake locks. I've tested them in hundreds of devices in production mode, and as you may know, every device is different when screen is switch off. Lot of Android surprises.

Anyway, the differences between Service and Foreground Service are minimal: widget, and priority level. Implementation is the same, so I though my advices my be useful for someone who get this thread and needs a minimal slightly different location service than you.

If you were offended by my post, I'm really sorry for you.

@betorobson
Copy link
Author

It is all good @AroundPixels , I have not get offended.
My concern it is just keep the mindset of this topic about Location service in Passive Mode.

@betorobson
Copy link
Author

Thanks, I found I send it back in a broadcast.

can you tell me how are you doing that I am really stuck here and I do not know how to do that for Pie devices.
Thank you

Are you trying to use the Passive Mode or High Accuracy geo location?

@hafiz013
Copy link

hafiz013 commented Mar 1, 2019

First you need class LocationUpdatesBroadcastReceiver extends BroadcastReceiver. Then inside broadcast :

`public static final String ACTION_PROCESS_UPDATES = "<id.package>.action" +
".PROCESS_UPDATES";

@Override
public void onReceive(Context context, Intent intent) {

    if (intent != null) {
        final String action = intent.getAction();

        if (ACTION_PROCESS_UPDATES.equals(action)) {
            Utils.setLocationUpdatesResult(context, DateFormat.getDateTimeInstance().format(new Date()));
            try {
                Utils.getLocationUpdates(context,intent,"PROCESS_UPDATES");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}`

after that, create class Utils which content static mehtod for pass value location and call notification builder.

`public static void getLocationUpdates(final Context context, final Intent intent, String broadcastevent){
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);

    PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
            new Intent(context, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);

    Notification.Builder notificationBuilder = new Notification.Builder(context)
            .setContentTitle(" ")
            .setContentText(" ")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(contentIntent)
            .setOngoing(true)
            .setStyle(new Notification.BigTextStyle().bigText(" "))
            .setAutoCancel(true);
    notificationManager.notify(3, notificationBuilder.build());

}`.

After that, in the main activity call this function:

`mFusedLocationClient.requestLocationUpdates(mLocationRequest, getPendingIntent());

    LocationRequestHelper.getInstance(getActivity()).setValue("RequestingLocationUpdates",true);

    Task<Void> task = mActivityRecognitionClient.requestActivityUpdates(
            Utils.UPDATE_INTERVAL,
            getPendingIntent());

    task.addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void result) {

        }
    });
    task.addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            //Log.i(TAG, "addOnFailureListener mActivityRecognitionClient "+e);
        }
    });`

and function getPending like this;

private PendingIntent getPendingIntent() { Intent intent = new Intent(getActivity(), LocationUpdatesBroadcastReceiver.class); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.setAction(LocationUpdatesBroadcastReceiver.ACTION_PROCESS_UPDATES); return PendingIntent.getBroadcast(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); }

That's all due, and for stop update location:

` if (getPendingIntent() != null && mFusedLocationClient != null) {
mFusedLocationClient.removeLocationUpdates(getPendingIntent());
}

    Utils.removeNotification(getActivity());

    if (getPendingIntent() != null && mActivityRecognitionClient != null) {
        Task<Void> task = mActivityRecognitionClient.removeActivityUpdates(
                getPendingIntent());

        task.addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void result) {
            }
        });
        task.addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {

            }
        });
    }`

function remove notification:

public static void removeNotification(Context context){ NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); notificationManager.cancelAll(); }

@BlackBlind567
Copy link

Thanks sir for your great reply but here you can see my problem . Can you please shot out my problem I really need your valuable help.
Thank You

@BlackBlind567
Copy link

First you need class LocationUpdatesBroadcastReceiver extends BroadcastReceiver. Then inside broadcast :

`public static final String ACTION_PROCESS_UPDATES = "<id.package>.action" +
".PROCESS_UPDATES";

@Override
public void onReceive(Context context, Intent intent) {

    if (intent != null) {
        final String action = intent.getAction();

        if (ACTION_PROCESS_UPDATES.equals(action)) {
            Utils.setLocationUpdatesResult(context, DateFormat.getDateTimeInstance().format(new Date()));
            try {
                Utils.getLocationUpdates(context,intent,"PROCESS_UPDATES");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}`

after that, create class Utils which content static mehtod for pass value location and call notification builder.

`public static void getLocationUpdates(final Context context, final Intent intent, String broadcastevent){
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);

    PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
            new Intent(context, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);

    Notification.Builder notificationBuilder = new Notification.Builder(context)
            .setContentTitle(" ")
            .setContentText(" ")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(contentIntent)
            .setOngoing(true)
            .setStyle(new Notification.BigTextStyle().bigText(" "))
            .setAutoCancel(true);
    notificationManager.notify(3, notificationBuilder.build());

}`.

After that, in the main activity call this function:

`mFusedLocationClient.requestLocationUpdates(mLocationRequest, getPendingIntent());

    LocationRequestHelper.getInstance(getActivity()).setValue("RequestingLocationUpdates",true);

    Task<Void> task = mActivityRecognitionClient.requestActivityUpdates(
            Utils.UPDATE_INTERVAL,
            getPendingIntent());

    task.addOnSuccessListener(new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void result) {

        }
    });
    task.addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            //Log.i(TAG, "addOnFailureListener mActivityRecognitionClient "+e);
        }
    });`

and function getPending like this;

private PendingIntent getPendingIntent() { Intent intent = new Intent(getActivity(), LocationUpdatesBroadcastReceiver.class); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.setAction(LocationUpdatesBroadcastReceiver.ACTION_PROCESS_UPDATES); return PendingIntent.getBroadcast(getActivity(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); }

That's all due, and for stop update location:

` if (getPendingIntent() != null && mFusedLocationClient != null) {
mFusedLocationClient.removeLocationUpdates(getPendingIntent());
}

    Utils.removeNotification(getActivity());

    if (getPendingIntent() != null && mActivityRecognitionClient != null) {
        Task<Void> task = mActivityRecognitionClient.removeActivityUpdates(
                getPendingIntent());

        task.addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void result) {
            }
        });
        task.addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {

            }
        });
    }`

function remove notification:

public static void removeNotification(Context context){ NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); notificationManager.cancelAll(); }

Thanks sir for your great reply but here you can see my problem . Can you please shot out my problem I really need your valuable help.
Thank You

@hafiz013
Copy link

sorry due, in order to get location from service to be served to another activity is quite difficult and i do not know how to do it.

@BlackBlind567
Copy link

I know it was late but you can find best code here

@olimdzhon
Copy link

I know it was late but you can find best code here

hi, i'm getting this error could you help me? MainActivity$2.onClick(MainActivity.java:99)
at android.view.View.performClick(View.java:4508)
at android.view.View$PerformClick.run(View.java:18675)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5590)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1280)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1096)
at dalvik.system.NativeStart.main(Native Method)

@BlackBlind567
Copy link

I know it was late but you can find best code here

hi, i'm getting this error could you help me? MainActivity$2.onClick(MainActivity.java:99)
at android.view.View.performClick(View.java:4508)
at android.view.View$PerformClick.run(View.java:18675)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5590)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1280)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1096)
at dalvik.system.NativeStart.main(Native Method)

Sorry I am unable to get your problem can you describe more??

@olimdzhon
Copy link

I know it was late but you can find best code here

hi, i'm getting this error could you help me? MainActivity$2.onClick(MainActivity.java:99)
at android.view.View.performClick(View.java:4508)
at android.view.View$PerformClick.run(View.java:18675)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5590)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1280)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1096)
at dalvik.system.NativeStart.main(Native Method)

Sorry I am unable to get your problem can you describe more??

I'm sorry my bad... i tried to use this code on API 19, and when you click the button app crushes

@BlackBlind567
Copy link

I know it was late but you can find best code here

hi, i'm getting this error could you help me? MainActivity$2.onClick(MainActivity.java:99)
at android.view.View.performClick(View.java:4508)
at android.view.View$PerformClick.run(View.java:18675)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5590)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1280)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1096)
at dalvik.system.NativeStart.main(Native Method)

Sorry I am unable to get your problem can you describe more??

I'm sorry my bad... i tried to use this code on API 19, and when you click the button app crushes

Pay attention here ...

  1. If problem with my repository you have to open a issue there.
  2. Bro according to my repository gradle file have min Sdk is 22 so if you want to use in 19 so change a gradle file.

Thank You !

@softronetMoitri
Copy link

I have used the code from SO linked above too, but how do I pass the location found back to my app, so I can update location information in Firebase? Thanks!

Can you please provide the full code?

@BlackBlind567
Copy link

I have used the code from SO linked above too, but how do I pass the location found back to my app, so I can update location information in Firebase? Thanks!

Can you please provide the full code?

You can check my repository . I mentioned a link above.

@GadepalliAditya1998
Copy link

run a foreground service and fetch location by location listener. Your app wont be killed and will work all the time. or Use activity recognition API to detect user movements and run location fetching code.

@jordan-lumley
Copy link

run a foreground service and fetch location by location listener. Your app wont be killed and will work all the time. or Use activity recognition API to detect user movements and run location fetching code.

I have done this via a foreground service. Everything works out very well. However, I am curious on if doze mode or wakelock affects foreground services? And every call that comes from the onNewLocation handler, I send the data to a restful api to store then able to view on the admin side, it is killing battery though. Any pointers?

@kpradeepkumarreddy
Copy link

In a foreground service, i'm using FusedLocationProviderClient to request for location updates. If the gps is turned off then i'm not getting the onLocationResult() call back. How to handle this problem ?? Before starting the service, location was on and i got a couple of callbacks in onLocationResult() method. After sometime, user turned off the gps, after that i'm not getting the onLocationResult() call back. Any idea how to deal with this problem ??

@shrawanibawage
Copy link

shrawanibawage commented Dec 3, 2020

Can anybody help me out
I am building an application with following specs:
· This app is aimed to record trips of the user.

· Whenever user wants to go on a trip, he/she will START the trip. The app will record the location (through GPS/4G) at specific interval of time (e.g. 10 seconds, 1 minute etc, a configurable value through menu). Whenever user finishes the trip, he/she will STOP the trip.

· All trips will be saved locally on the mobile. User should be shown the list of all saved trips. Any trip should be selectable, which will fetch the saved data, in form of table.

· Next step will be, integration with GoogleMaps library. All recorded location points should be plotted on GoogleMaps view, to show entire trip (not in GoogleMaps app, but in Track-My-Trip app itself).

· GoogleMaps view can be used for live tracking of current trip, updated real time.

Following key elements should be used:
-Android Studio
-LocationManager APIs
-data storing methods, e.g. SharedPreferences or SQLite DB
-Learn Google Maps APIs
-Learn Android App UI Components

Outcomes:
· Recording of data for 1 trip.
· List of all saved trips
· Loading of data of selected trip
· Plotting of Trip data on Google Maps
· Live plotting of location data on Google Maps view

@GadepalliAditya1998
Copy link

Hey @99002688, Should the location tracking should happen in the background or while the app is open. If you want to track while the app is open you can create an app with a Wake lock that will not turn off the screen until the user presses the power button.

With this approach, you will write a location tracking broadcast using fused location API and create a pending Intent that will generate a Broadcast and in broadcast just do what you want to do with the data or you can have callbacks too and in the locationresult callback just write the code what you want to do with the coordinates.

If needed in background even when the app is closed and removed from the activity stack, I prefer you to go with Foreground service approach. Create a Foreground service that will have Fused location API code and in the location result do what ever you want.

Note: Foreground services may be stopped in some chinese devices like Xiaomi, Realme, Oppo, Vivo etc. For those devices I went with Alarm manager approach which will trigger foreground services for every given time. (Note > 10 min) and some may work with 5 min too.

Alarm managers are vulnerable to doze mode conditions i.e. they may get delayed when device goes to doze mode. for that i have used One of the Wake lock which will turn on the screen to make device come out of doze mode. (FULL_BRIGHTNESS) .

@Nahush22
Copy link

Nahush22 commented Jan 24, 2021

Hello @GadepalliAditya1998 . Do all Chinese manufacturers restrict location access from any kind of background activity. I tried getting location periodically in the background using normal services, foreground service & WorkManager. But each time, after 10s of the phone being locked, the location wasn't being tracked anymore.

I actually created a broadcast receiver that starts a WorkManager when powerbutton is clicked but even then while the WorkManager is started, I am not getting location data. Same happens with Foreground service.

On the other hand, turning the Battery Saver option of the app to no restrictions fixes this & now I am able to access location long(15-20 mins) after the phone has been locked.

Is WakeLock the only solution or is there any other way. Can WakeLocks be initiated from Broadcast receivers? My problem is that while the service/workmanager itself runs, unfortunately I am not getting location data.

@GadepalliAditya1998
Copy link

GadepalliAditya1998 commented Jan 25, 2021 via email

@Nahush22
Copy link

You see...my problem isn't with Foreground service or WorkManager not running. Both run just fine in the background whenever they are called even when the device is locked. But my problem is, for some reason location access is being restricted to these services while they run in the background after the device is locked. When I turn off all battery saving features then the location data gets properly passed to the Foreground service/WorkManager & they are able to store it in Firebase.

Is there anyway to go around the battery saving feature of Chinese ROMS to get location access? Or does the battery saving feature also control doze mode & me disabling the feature also disables it? If so should I proceed with a WakeLock since I read somewhere else that Chinese roms restrict location access for even foreground services & only WakeLock fixes it?

@GadepalliAditya1998
Copy link

GadepalliAditya1998 commented Jan 25, 2021 via email

@HusniddinUmarov
Copy link

hello who can help me google map doesn't work in the background I looked at the replies but it doesn't work

@EnKattral
Copy link

I am a mobile app development learner/beginner. I am in the lookout for a sample code for tracking and logging location in the background. Can you all please help me with the sample code where the MyLocationService code from this thread is used... Thank You...

@IamMuhammadHasib
Copy link

private fun locationEnable(): Boolean {
var locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(
LocationManager.NETWORK_PROVIDER
)
}

@KhamdamovDilmurod
Copy link

are there kotlin example?

@jamshidmuxtaraliev
Copy link

Hello everyone. Is there a version of the same codes written in Kotlin?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests