Лучший способ получить пользовательское местоположение GPS в фоновом режиме в Android

В моем приложении для Android я хочу получать текущее местоположение пользователя каждые несколько минут и обновляться на моем сервере центра с помощью веб-службы. В настоящее время я использую Fused Location Provide для получения текущего местоположения пользователя, см. Ссылку

Теперь я хочу узнать, как лучше всего часто узнавать местоположение пользователя и звонить в веб-службу.

ниже мой код, который дает мне текущее местоположение пользователя: -

     locationrequest = LocationRequest.create();
     locationrequest.setInterval(10000);
     locationclient.requestLocationUpdates(locationrequest,new com.google.android.gms.location.LocationListener() {

        @Override
        public void onLocationChanged(Location location) {
              Log.i(TAG, "Last Known Location :" + location.getLatitude() + "," + location.getLongitude());
        }
    });

теперь откуда я должен назвать этот код. Могу ли я использовать это в фоновом режиме или где-то еще.

Пожалуйста, предоставьте вашу идею.

ТИА.

14 ответов

Решение

Вы должны использовать Service:

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service
{
    private static final String TAG = "BOOMBOOMTESTGPS";
    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)
    };

    @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.NETWORK_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, "network provider does not exist, " + ex.getMessage());
        }
        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.GPS_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, "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 {
                    mLocationManager.removeUpdates(mLocationListeners[i]);
                } catch (Exception ex) {
                    Log.i(TAG, "fail to remove location listners, ignore", ex);
                }
            }
        }
    }

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

Ваш AndroidManifest.xml будет выглядеть примерно так:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity android:label="@string/app_name" android:name=".LocationCheckerActivity" >
        <intent-filter >
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service android:name=".MyService" android:process=":my_service" />
</application>

Ни один из остальных ответов не использует:

com.google.android.gms.location.FusedLocationProviderClient

Который является провайдером объединенных локаций и основной точкой входа для взаимодействия с провайдером объединенных локаций со стороны Google, и найти хороший пример очень сложно. Это было выпущено в середине 2017 года Google.

API определения местоположения сервисов Google Play предпочтительнее API определения местоположения платформы Android (android.location)

Если вы в настоящее время используете API-интерфейсы определения местоположения платформы Android, настоятельно рекомендуется как можно скорее переключиться на API-интерфейсы определения местоположения служб Google Play.

Чтобы использовать API определения местоположения Google, сначала добавьте это в свой build.gradle

compile 'com.google.android.gms:play-services:11.0.0'

Тогда вы можете использовать этот класс Wherebouts.java:

import android.location.Location;
import android.os.Looper;
import android.util.Log;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;

/**
 * Uses Google Play API for obtaining device locations
 * Created by alejandro.tkachuk 
 * alejandro@calculistik.com
 * www.calculistik.com Mobile Development
 */

public class Wherebouts {

    private static final Wherebouts instance = new Wherebouts();

    private static final String TAG = Wherebouts.class.getSimpleName();

    private FusedLocationProviderClient mFusedLocationClient;
    private LocationCallback locationCallback;
    private LocationRequest locationRequest;
    private LocationSettingsRequest locationSettingsRequest;

    private Workable<GPSPoint> workable;

    private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000;
    private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 1000;

    private Wherebouts() {
        this.locationRequest = new LocationRequest();
        this.locationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        this.locationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        this.locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        builder.addLocationRequest(this.locationRequest);
        this.locationSettingsRequest = builder.build();

        this.locationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult); // why? this. is. retarded. Android.
                Location currentLocation = locationResult.getLastLocation();

                GPSPoint gpsPoint = new GPSPoint(currentLocation.getLatitude(), currentLocation.getLongitude());
                Log.i(TAG, "Location Callback results: " + gpsPoint);
                if (null != workable)
                    workable.work(gpsPoint);
            }
        };

        this.mFusedLocationClient = LocationServices.getFusedLocationProviderClient(MainApplication.getAppContext());
        this.mFusedLocationClient.requestLocationUpdates(this.locationRequest,
                this.locationCallback, Looper.myLooper());
    }

    public static Wherebouts instance() {
        return instance;
    }

    public void onChange(Workable<GPSPoint> workable) {
        this.workable = workable;
    }

    public LocationSettingsRequest getLocationSettingsRequest() {
        return this.locationSettingsRequest;
    }

    public void stop() {
        Log.i(TAG, "stop() Stopping location tracking");
        this.mFusedLocationClient.removeLocationUpdates(this.locationCallback);
    }

}

Из вашей деятельности вы можете использовать его следующим образом: Workable объект. Работоспособный объект - это не что иное, как пользовательский объект Callback.

 Wherebouts.instance().onChange(workable);

Используя обратный вызов, такой как Workable, вы напишете код, связанный с пользовательским интерфейсом, в своей Activity и оставите суету работы с GPS классу помощника, например, Wherebouts.

    new Workable<GPSPoint>() {
        @Override
        public void work(GPSPoint gpsPoint) {
            // draw something in the UI with this new data
        }
    };

Конечно, вам нужно будет запросить соответствующие разрешения для ОС Android для вашего приложения. Вы можете прочитать следующую документацию для получения дополнительной информации об этом или сделать некоторые исследования.

Загрузите исходный код отсюда ( Получить текущее местоположение с помощью фоновой службы)

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="servicetutorial.service">

    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".GoogleService"></service>
    </application>

</manifest>

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#ffffff"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#3F51B5"
        android:text="Location using service"
        android:textColor="#ffffff"
        android:textSize="20dp"
        android:gravity="center"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"

        android:orientation="vertical">



    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:layout_height="50dp">

        <TextView
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:text="Latitude"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="10dp"
            android:textColor="#000000"
            android:textSize="20dp"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""
            android:id="@+id/tv_latitude"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="10dp"
            android:textColor="#000000"
            android:textSize="20dp"/>


    </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:orientation="horizontal"
            android:layout_height="50dp">

            <TextView
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:text="Longitude"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="10dp"
                android:textColor="#000000"
                android:textSize="20dp"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                android:id="@+id/tv_longitude"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="10dp"
                android:textColor="#000000"
                android:textSize="20dp"/>


        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:orientation="horizontal"
            android:layout_height="50dp">

            <TextView
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:text="Address"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="10dp"
                android:textColor="#000000"
                android:textSize="20dp"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                android:id="@+id/tv_address"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="10dp"
                android:textColor="#000000"
                android:textSize="20dp"/>


        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:orientation="horizontal"
            android:layout_height="50dp">

            <TextView
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:text="Area"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="10dp"
                android:textColor="#000000"
                android:textSize="20dp"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                android:id="@+id/tv_area"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="10dp"
                android:textColor="#000000"
                android:textSize="20dp"/>


        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:orientation="horizontal"
            android:layout_height="50dp">

            <TextView
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:text="Locality"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="10dp"
                android:textColor="#000000"
                android:textSize="20dp"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=""
                android:id="@+id/tv_locality"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="10dp"
                android:textColor="#000000"
                android:textSize="20dp"/>


        </LinearLayout>

    </LinearLayout>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btn_start"
        android:text="Get Location"
        android:layout_alignParentBottom="true"/>



</RelativeLayout>

MainActivity.java

package servicetutorial.service;

import android.*;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.preference.PreferenceManager;
import android.renderscript.Double2;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

public class MainActivity extends Activity {
    Button btn_start;
    private static final int REQUEST_PERMISSIONS = 100;
    boolean boolean_permission;
    TextView tv_latitude, tv_longitude, tv_address,tv_area,tv_locality;
    SharedPreferences mPref;
    SharedPreferences.Editor medit;
    Double latitude,longitude;
    Geocoder geocoder;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_start = (Button) findViewById(R.id.btn_start);
        tv_address = (TextView) findViewById(R.id.tv_address);
        tv_latitude = (TextView) findViewById(R.id.tv_latitude);
        tv_longitude = (TextView) findViewById(R.id.tv_longitude);
        tv_area = (TextView)findViewById(R.id.tv_area);
        tv_locality = (TextView)findViewById(R.id.tv_locality);
        geocoder = new Geocoder(this, Locale.getDefault());
        mPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
        medit = mPref.edit();


        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (boolean_permission) {

                    if (mPref.getString("service", "").matches("")) {
                        medit.putString("service", "service").commit();

                        Intent intent = new Intent(getApplicationContext(), GoogleService.class);
                        startService(intent);

                    } else {
                        Toast.makeText(getApplicationContext(), "Service is already running", Toast.LENGTH_SHORT).show();
                    }
                } else {
                    Toast.makeText(getApplicationContext(), "Please enable the gps", Toast.LENGTH_SHORT).show();
                }

            }
        });

        fn_permission();
    }

    private void fn_permission() {
        if ((ContextCompat.checkSelfPermission(getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {

            if ((ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION))) {


            } else {
                ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION

                        },
                        REQUEST_PERMISSIONS);

            }
        } else {
            boolean_permission = true;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        switch (requestCode) {
            case REQUEST_PERMISSIONS: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    boolean_permission = true;

                } else {
                    Toast.makeText(getApplicationContext(), "Please allow the permission", Toast.LENGTH_LONG).show();

                }
            }
        }
    }

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            latitude = Double.valueOf(intent.getStringExtra("latutide"));
            longitude = Double.valueOf(intent.getStringExtra("longitude"));

            List<Address> addresses = null;

            try {
                addresses = geocoder.getFromLocation(latitude, longitude, 1);
                String cityName = addresses.get(0).getAddressLine(0);
                String stateName = addresses.get(0).getAddressLine(1);
                String countryName = addresses.get(0).getAddressLine(2);

                tv_area.setText(addresses.get(0).getAdminArea());
                tv_locality.setText(stateName);
                tv_address.setText(countryName);



            } catch (IOException e1) {
                e1.printStackTrace();
            }


            tv_latitude.setText(latitude+"");
            tv_longitude.setText(longitude+"");
            tv_address.getText();


        }
    };

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(broadcastReceiver, new IntentFilter(GoogleService.str_receiver));

    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(broadcastReceiver);
    }


}

GoogleService.java

package servicetutorial.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by deepshikha on 24/11/16.
 */

public class GoogleService extends Service implements LocationListener{

    boolean isGPSEnable = false;
    boolean isNetworkEnable = false;
    double latitude,longitude;
    LocationManager locationManager;
    Location location;
    private Handler mHandler = new Handler();
    private Timer mTimer = null;
    long notify_interval = 1000;
    public static String str_receiver = "servicetutorial.service.receiver";
    Intent intent;




    public GoogleService() {

    }

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

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

        mTimer = new Timer();
        mTimer.schedule(new TimerTaskToGetLocation(),5,notify_interval);
        intent = new Intent(str_receiver);
//        fn_getlocation();
    }

    @Override
    public void onLocationChanged(Location location) {

    }

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

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }

    private void fn_getlocation(){
        locationManager = (LocationManager)getApplicationContext().getSystemService(LOCATION_SERVICE);
        isGPSEnable = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        isNetworkEnable = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (!isGPSEnable && !isNetworkEnable){

        }else {

            if (isNetworkEnable){
                location = null;
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,1000,0,this);
                if (locationManager!=null){
                    location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                    if (location!=null){

                        Log.e("latitude",location.getLatitude()+"");
                        Log.e("longitude",location.getLongitude()+"");

                        latitude = location.getLatitude();
                        longitude = location.getLongitude();
                        fn_update(location);
                    }
                }

            }


            if (isGPSEnable){
                location = null;
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,0,this);
                if (locationManager!=null){
                    location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                    if (location!=null){
                        Log.e("latitude",location.getLatitude()+"");
                        Log.e("longitude",location.getLongitude()+"");
                        latitude = location.getLatitude();
                        longitude = location.getLongitude();
                        fn_update(location);
                    }
                }
            }


        }

    }

    private class TimerTaskToGetLocation extends TimerTask{
        @Override
        public void run() {

            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    fn_getlocation();
                }
            });

        }
    }

    private void fn_update(Location location){

        intent.putExtra("latutide",location.getLatitude()+"");
        intent.putExtra("longitude",location.getLongitude()+"");
        sendBroadcast(intent);
    }


}

Добавить эту зависимость

compile 'com.google.android.gms:play-services:9.4.0'

Предоставить необходимое разрешение ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION после запуска службы

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.location.Location;
import android.location.LocationListener;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
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.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.tasks.OnCanceledListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;

import java.util.concurrent.TimeUnit;

/**
 * Created by Ketan Ramani on 05/11/18.
 */

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

    /* Declare in manifest
    <service android:name=".BackgroundBackgroundLocationUpdateService"/>
    */

    private final String TAG = "BackgroundBackgroundLocationUpdateService";
    private final String TAG_LOCATION = "TAG_LOCATION";
    private Context context;
    private boolean stopService = false;

    /* For Google Fused API */
    protected GoogleApiClient mGoogleApiClient;
    protected LocationSettingsRequest mLocationSettingsRequest;
    private String latitude = "0.0", longitude = "0.0";
    private FusedLocationProviderClient mFusedLocationClient;
    private SettingsClient mSettingsClient;
    private LocationCallback mLocationCallback;
    private LocationRequest mLocationRequest;
    private Location mCurrentLocation;
    /* For Google Fused API */

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        StartForeground();
        final Handler handler = new Handler();
        final Runnable runnable = new Runnable() {

            @Override
            public void run() {
                try {
                    if (!stopService) {
                        //Perform your task here
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (!stopService) {
                        handler.postDelayed(this, TimeUnit.SECONDS.toMillis(10));
                    }
                }
            }
        };
        handler.postDelayed(runnable, 2000);

        buildGoogleApiClient();

        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "Service Stopped");
        stopService = true;
        if (mFusedLocationClient != null) {
            mFusedLocationClient.removeLocationUpdates(mLocationCallback);
            Log.e(TAG_LOCATION, "Location Update Callback Removed");
        }
        super.onDestroy();
    }

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

    private void StartForeground() {
        Intent intent = new Intent(context, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT);

        String CHANNEL_ID = "channel_location";
        String CHANNEL_NAME = "channel_location";

        NotificationCompat.Builder builder = null;
        NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
            channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
            notificationManager.createNotificationChannel(channel);
            builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID);
            builder.setChannelId(CHANNEL_ID);
            builder.setBadgeIconType(NotificationCompat.BADGE_ICON_NONE);
        } else {
            builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID);
        }

        builder.setContentTitle("Your title");
        builder.setContentText("You are now online");
        Uri notificationSound = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_NOTIFICATION);
        builder.setSound(notificationSound);
        builder.setAutoCancel(true);
        builder.setSmallIcon(R.drawable.ic_logo);
        builder.setContentIntent(pendingIntent);
        Notification notification = builder.build();
        startForeground(101, notification);
    }

    @Override
    public void onLocationChanged(Location location) {
        Log.e(TAG_LOCATION, "Location Changed Latitude : " + location.getLatitude() + "\tLongitude : " + location.getLongitude());

        latitude = String.valueOf(location.getLatitude());
        longitude = String.valueOf(location.getLongitude());

        if (latitude.equalsIgnoreCase("0.0") && longitude.equalsIgnoreCase("0.0")) {
            requestLocationUpdate();
        } else {
            Log.e(TAG_LOCATION, "Latitude : " + location.getLatitude() + "\tLongitude : " + location.getLongitude());
        }
    }

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

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10 * 1000);
        mLocationRequest.setFastestInterval(5 * 1000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        builder.addLocationRequest(mLocationRequest);
        builder.setAlwaysShow(true);
        mLocationSettingsRequest = builder.build();

        mSettingsClient
                .checkLocationSettings(mLocationSettingsRequest)
                .addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
                    @Override
                    public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
                        Log.e(TAG_LOCATION, "GPS Success");
                        requestLocationUpdate();
                    }
                }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                int statusCode = ((ApiException) e).getStatusCode();
                switch (statusCode) {
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        try {
                            int REQUEST_CHECK_SETTINGS = 214;
                            ResolvableApiException rae = (ResolvableApiException) e;
                            rae.startResolutionForResult((AppCompatActivity) context, REQUEST_CHECK_SETTINGS);
                        } catch (IntentSender.SendIntentException sie) {
                            Log.e(TAG_LOCATION, "Unable to execute request.");
                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        Log.e(TAG_LOCATION, "Location settings are inadequate, and cannot be fixed here. Fix in Settings.");
                }
            }
        }).addOnCanceledListener(new OnCanceledListener() {
            @Override
            public void onCanceled() {
                Log.e(TAG_LOCATION, "checkLocationSettings -> onCanceled");
            }
        });
    }

    @Override
    public void onConnectionSuspended(int i) {
        connectGoogleClient();
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        buildGoogleApiClient();
    }

    protected synchronized void buildGoogleApiClient() {
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
        mSettingsClient = LocationServices.getSettingsClient(context);

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

        connectGoogleClient();

        mLocationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                Log.e(TAG_LOCATION, "Location Received");
                mCurrentLocation = locationResult.getLastLocation();
                onLocationChanged(mCurrentLocation);
            }
        };
    }

    private void connectGoogleClient() {
        GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
        int resultCode = googleAPI.isGooglePlayServicesAvailable(context);
        if (resultCode == ConnectionResult.SUCCESS) {
            mGoogleApiClient.connect();
        }
    }

    @SuppressLint("MissingPermission")
    private void requestLocationUpdate() {
        mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
    }
}

В деятельности

Начать обслуживание: startService(new Intent(this, BackgroundLocationUpdateService.class));

Остановить службу: stopService(new Intent(this, BackgroundLocationUpdateService.class));

Во фрагменте

Начать обслуживание: getActivity().startService(new Intent(getActivity().getBaseContext(), BackgroundLocationUpdateService.class));

Остановить службу: getActivity().stopService(new Intent(getActivity(), BackgroundLocationUpdateService.class));

Использование: GCM Network Manager

Запустите это, чтобы запустить периодическое задание, которое будет запускаться даже после перезагрузки:

PeriodicTask task = new PeriodicTask.Builder()
    .setService(MyLocationService.class)
    .setTag("periodic")
    .setPeriod(30L)
    .setPersisted(true)
    .build();
mGcmNetworkManager.schedule(task);

затем в onRunTask() получить текущее местоположение и использовать его (в этом примере событие отправляется в конце, чтобы пользовательский интерфейс узнал, что местоположение было найдено):

    public void getLastKnownLocation() {
    Location lastKnownGPSLocation;
    Location lastKnownNetworkLocation;
    String gpsLocationProvider = LocationManager.GPS_PROVIDER;
    String networkLocationProvider = LocationManager.NETWORK_PROVIDER;

    try {
        locationManager = (LocationManager) App.get().getSystemService(Context.LOCATION_SERVICE);

        lastKnownNetworkLocation = locationManager.getLastKnownLocation(networkLocationProvider);
        lastKnownGPSLocation = locationManager.getLastKnownLocation(gpsLocationProvider);

        if (lastKnownGPSLocation != null) {
            Log.i(TAG, "lastKnownGPSLocation is used.");
            this.mCurrentLocation = lastKnownGPSLocation;
        } else if (lastKnownNetworkLocation != null) {
            Log.i(TAG, "lastKnownNetworkLocation is used.");
            this.mCurrentLocation = lastKnownNetworkLocation;
        } else {
            Log.e(TAG, "lastLocation is not known.");
            return;
        }

        LocationChangedEvent event = new LocationChangedEvent();
        event.setLocation(mCurrentLocation);
        EventHelper.publishEvent(event);

    } catch (SecurityException sex) {
        Log.e(TAG, "Location permission is not granted!");
    }

    return;
}

MyLocationService в целом:

public class MyLocationService extends GcmTaskService {
private static final String TAG = MyLocationService.class.getSimpleName();

private LocationManager locationManager;
private Location mCurrentLocation;

public static final String TASK_GET_LOCATION_ONCE="location_oneoff_task";
public static final String TASK_GET_LOCATION_PERIODIC="location_periodic_task";


private static final int RC_PLAY_SERVICES = 123;

@Override
public void onInitializeTasks() {
    // When your package is removed or updated, all of its network tasks are cleared by
    // the GcmNetworkManager. You can override this method to reschedule them in the case of
    // an updated package. This is not called when your application is first installed.
    //
    // This is called on your application's main thread.
    startPeriodicLocationTask(TASK_GET_LOCATION_PERIODIC,
            30L, null);
}

@Override
public int onRunTask(TaskParams taskParams) {
    Log.d(TAG, "onRunTask: " + taskParams.getTag());

    String tag = taskParams.getTag();
    Bundle extras = taskParams.getExtras();
    // Default result is success.
    int result = GcmNetworkManager.RESULT_SUCCESS;

    switch (tag) {
        case TASK_GET_LOCATION_ONCE:
            getLastKnownLocation();
            break;

        case TASK_GET_LOCATION_PERIODIC:
            getLastKnownLocation();
            break;

    }

    return result;
}


public void getLastKnownLocation() {
    Location lastKnownGPSLocation;
    Location lastKnownNetworkLocation;
    String gpsLocationProvider = LocationManager.GPS_PROVIDER;
    String networkLocationProvider = LocationManager.NETWORK_PROVIDER;

    try {
        locationManager = (LocationManager) App.get().getSystemService(Context.LOCATION_SERVICE);

        lastKnownNetworkLocation = locationManager.getLastKnownLocation(networkLocationProvider);
        lastKnownGPSLocation = locationManager.getLastKnownLocation(gpsLocationProvider);

        if (lastKnownGPSLocation != null) {
            Log.i(TAG, "lastKnownGPSLocation is used.");
            this.mCurrentLocation = lastKnownGPSLocation;
        } else if (lastKnownNetworkLocation != null) {
            Log.i(TAG, "lastKnownNetworkLocation is used.");
            this.mCurrentLocation = lastKnownNetworkLocation;
        } else {
            Log.e(TAG, "lastLocation is not known.");
            return;
        }

        LocationChangedEvent event = new LocationChangedEvent();
        event.setLocation(mCurrentLocation);
        EventHelper.publishEvent(event);

    } catch (SecurityException sex) {
        Log.e(TAG, "Location permission is not granted!");
    }

    return;
}

public static void startOneOffLocationTask(String tag, Bundle extras) {
    Log.d(TAG, "startOneOffLocationTask");

    GcmNetworkManager mGcmNetworkManager = GcmNetworkManager.getInstance(App.get());
    OneoffTask.Builder taskBuilder = new OneoffTask.Builder()
            .setService(MyLocationService.class)
            .setTag(tag);

    if (extras != null) taskBuilder.setExtras(extras);

    OneoffTask task = taskBuilder.build();
    mGcmNetworkManager.schedule(task);
}

public static void startPeriodicLocationTask(String tag, Long period, Bundle extras) {
    Log.d(TAG, "startPeriodicLocationTask");

    GcmNetworkManager mGcmNetworkManager = GcmNetworkManager.getInstance(App.get());
    PeriodicTask.Builder taskBuilder = new PeriodicTask.Builder()
            .setService(MyLocationService.class)
            .setTag(tag)
            .setPeriod(period)
            .setPersisted(true)
            .setRequiredNetwork(Task.NETWORK_STATE_CONNECTED);

    if (extras != null) taskBuilder.setExtras(extras);

    PeriodicTask task = taskBuilder.build();
    mGcmNetworkManager.schedule(task);
}




public static boolean checkPlayServicesAvailable(Activity activity) {
    GoogleApiAvailability availability = GoogleApiAvailability.getInstance();
    int resultCode = availability.isGooglePlayServicesAvailable(App.get());

    if (resultCode != ConnectionResult.SUCCESS) {
        if (availability.isUserResolvableError(resultCode)) {
            // Show dialog to resolve the error.
            availability.getErrorDialog(activity, resultCode, RC_PLAY_SERVICES).show();
        }
        return false;
    } else {
        return true;
    }
}

Также добавьте эти 2 в AndroidManifest.xml:

 <manifest...
 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

 <application...
 <service
        android:name=".api.location.MyLocationService"
        android:exported="true"
        android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE">
        <intent-filter>
            <action android:name="com.google.android.gms.gcm.ACTION_TASK_READY" />
        </intent-filter>
    </service>

Вы должны создать сервис. Этот сервис должен реализовывать LocationListener. Затем Вы должны использовать AlarmManager для повторного вызова сервиса с определенным сроком.

Я надеюсь, что это поможет вам:)

Я попытался мой код и получил успех попробовать это

package com.mobeyosoft.latitudelongitude;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

/**
 * Created by 5943 6417 on 14-09-2016.
 */
public class LocationService extends Service
{
    public static final String BROADCAST_ACTION = "Hello World";
    private static final int TWO_MINUTES = 1000 * 60 * 1;
    public LocationManager locationManager;
    public MyLocationListener listener;
    public Location previousBestLocation = null;

    Context context;

    Intent intent;
    int counter = 0;

    @Override
    public void onCreate() {
        super.onCreate();
        intent = new Intent(BROADCAST_ACTION);
        context=this;
    }

    @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);
    }

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

    protected boolean isBetterLocation(Location location, Location currentBestLocation) {
        if (currentBestLocation == null) {
            // A new location is always better than no location
            return true;
        }

        // Check whether the new location fix is newer or older
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
        boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
        boolean isNewer = timeDelta > 0;

        // If it's been more than two minutes since the current location, use the new location
        // because the user has likely moved
        if (isSignificantlyNewer) {
            return true;
            // If the new location is more than two minutes older, it must be worse
        } else if (isSignificantlyOlder) {
            return false;
        }

        // Check whether the new location fix is more or less accurate
        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > 200;

        // Check if the old and new location are from the same provider
        boolean isFromSameProvider = isSameProvider(location.getProvider(),
                currentBestLocation.getProvider());

        // Determine location quality using a combination of timeliness and accuracy
        if (isMoreAccurate) {
            return true;
        } else if (isNewer && !isLessAccurate) {
            return true;
        } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
            return true;
        }
        return false;
    }



    /** Checks whether two providers are the same */
    private boolean isSameProvider(String provider1, String provider2) {
        if (provider1 == null) {
            return provider2 == null;
        }
        return provider1.equals(provider2);
    }



    @Override
    public void onDestroy() {
        // handler.removeCallbacks(sendUpdatesToUI);
        super.onDestroy();
        Log.v("STOP_SERVICE", "DONE");
        locationManager.removeUpdates(listener);
    }

    public static Thread performOnBackgroundThread(final Runnable runnable) {
        final Thread t = new Thread() {
            @Override
            public void run() {
                try {
                    runnable.run();
                } finally {

                }
            }
        };
        t.start();
        return t;
    }




    public class MyLocationListener implements LocationListener{

        public void onLocationChanged(final Location loc)
        {
            Log.i("**********", "Location changed");
            if(isBetterLocation(loc, previousBestLocation)) {
                loc.getLatitude();
                loc.getLongitude();
                Toast.makeText(context, "Latitude" + loc.getLatitude() + "\nLongitude"+loc.getLongitude(),Toast.LENGTH_SHORT).show();
                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)
        {

        }

    }
}

С помощью API LocationServices GoogleApiClient мы можем получить текущее местоположение пользователя / устройства за определенный промежуток времени. Это может быть добавлено в фоновую службу, которая обновляет Activity при обратных вызовах onLocationChanged.

Фоновая служба будет работать до тех пор, пока приложение существует в памяти и остается на панели уведомлений. Служба обрабатывает следующие функции,

  • Подключение к Google LocationServices API
  • Получение текущего местоположения
  • Обмен результатом с деятельностью

Служба с прослушивателем местоположения

 public class LocationMonitoringService extends Service implements
    GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
    LocationListener {
    ...
    ...
    ...
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    mLocationClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();

    mLocationRequest.setInterval(10000); //10 secs
    mLocationRequest.setFastestInterval(5000); //5 secs


    int priority = LocationRequest.PRIORITY_HIGH_ACCURACY; //by default
    //PRIORITY_BALANCED_POWER_ACCURACY, PRIORITY_LOW_POWER, PRIORITY_NO_POWER are the other priority modes


    mLocationRequest.setPriority(priority);
    mLocationClient.connect();

    //Make it stick to the notification panel so it is less prone to get cancelled by the Operating System.
    return START_STICKY;
    }

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

    /*
    * LOCATION CALLBACKS
    */
    @Override
    public void onConnected(Bundle dataBundle) {
    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.

        Log.d(TAG, "== Error On onConnected() Permission not granted");
        //Permission not granted by user so cancel the further execution.
        return;
    }
    LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, mLocationRequest, this);

     Log.d(TAG, "Connected to Google API");
     }

    /*
     * Called by Location Services if the connection to the
     * location client drops because of an error.
     */
     @Override
     public void onConnectionSuspended(int i) {
       Log.d(TAG, "Connection suspended");
     }

     @Override
     public void onConnectionFailed(ConnectionResult connectionResult) {
       Log.d(TAG, "Failed to connect to Google API");
     }

     //to get the location change
     @Override
     public void onLocationChanged(Location location) {
       Log.d(TAG, "Location changed");

       if (location != null) {               

           //Do something with the location details,             
           if (location != null) {
           //call your API
             callAPI(String.valueOf(location.getLatitude()), String.valueOf(location.getLongitude()));
           }

      }
     }
    }

См. Полный учебник с исходным кодом и подробное описание >>;;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.GeomagneticField;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.widget.Toast;


public class LocationService extends Service {
    private static final int MINUTES = 1000 * 60 * 2;
    public LocationManager locationManager;
    public MyLocationListener listener;
    public Location previousBestLocation = null;
    Context mContext;
    private boolean isGpsEnabled = false;
    private boolean isNetworkEnabled = false;

    private GeomagneticField geoField;
    private double latitude = 0.0;
    private double longitude = 0.0;


    @Override
    public void onCreate() {
        super.onCreate();
        mContext = getApplicationContext();
        if (locationManager == null) {
            locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
        }
        getCurrentLocation();
    }

    private void getCurrentLocation() {
        try {
            assert locationManager != null;
            isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        if (!isGpsEnabled && !isNetworkEnabled) {
            showSettingsAlert();
        }
        listener = new MyLocationListener();

        try {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 0, listener);
            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 0, listener);
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }

    private void showSettingsAlert() {
        Toast.makeText(mContext, "GPS is disabled in your device. Please Enable it ?", Toast.LENGTH_LONG).show();
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mContext.startActivity(intent);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

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

    protected boolean isBetterLocation(Location location, Location currentBestLocation) {
        if (currentBestLocation == null) {
            return true;
        }
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isSignificantlyNewer = timeDelta > MINUTES;
        boolean isSignificantlyOlder = timeDelta < -MINUTES;
        boolean isNewer = timeDelta > 0;

        if (isSignificantlyNewer) {
            return true;
        } else if (isSignificantlyOlder) {
            return false;
        }

        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > 200;
        boolean isFromSameProvider = isSameProvider(location.getProvider(), currentBestLocation.getProvider());
        if (isMoreAccurate) {
            return true;
        } else if (isNewer && !isLessAccurate) {
            return true;
        } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
            return true;
        }
        return false;
    }


    private boolean isSameProvider(String provider1, String provider2) {
        if (provider1 == null) {
            return provider2 == null;
        }
        return provider1.equals(provider2);
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        locationManager.removeUpdates(listener);
    }

    private void setupFinalLocationData(Location mLocation) {
        if (mLocation != null) {
            geoField = new GeomagneticField(
                    Double.valueOf(mLocation.getLatitude()).floatValue(),
                    Double.valueOf(mLocation.getLongitude()).floatValue(),
                    Double.valueOf(mLocation.getAltitude()).floatValue(),
                    System.currentTimeMillis()
            );

            latitude = mLocation.getLatitude();
            longitude = mLocation.getLongitude();
            //Update latitude and longtitude in SharedPreference...
        }
    }

    public class MyLocationListener implements LocationListener {
        public void onLocationChanged(final Location loc) {
            if (isBetterLocation(loc, previousBestLocation)) {
                setupFinalLocationData(loc);
            }
        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

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

- Котлин версия

package com.ps.salestrackingapp.Services

import android.app.Service
import android.content.Context
import android.content.Intent
import android.location.Location
import android.location.LocationManager
import android.os.Bundle
import android.os.IBinder
import android.util.Log

 class LocationService : Service() {
    private var mLocationManager: LocationManager? = null

    var mLocationListeners = arrayOf(LocationListener(LocationManager.GPS_PROVIDER), LocationListener(LocationManager.NETWORK_PROVIDER))

     class LocationListener(provider: String) : android.location.LocationListener {
        internal var mLastLocation: Location

        init {
            Log.e(TAG, "LocationListener $provider")
            mLastLocation = Location(provider)
        }

        override fun onLocationChanged(location: Location) {
            Log.e(TAG, "onLocationChanged: $location")
            mLastLocation.set(location)
            Log.v("LastLocation", mLastLocation.latitude.toString() +"  " + mLastLocation.longitude.toString())
        }

        override fun onProviderDisabled(provider: String) {
            Log.e(TAG, "onProviderDisabled: $provider")
        }

        override fun onProviderEnabled(provider: String) {
            Log.e(TAG, "onProviderEnabled: $provider")
        }

        override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
            Log.e(TAG, "onStatusChanged: $provider")
        }
    }

    override fun onBind(arg0: Intent): IBinder? {
        return null
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.e(TAG, "onStartCommand")
        super.onStartCommand(intent, flags, startId)
        return Service.START_STICKY
    }

    override fun onCreate() {
        Log.e(TAG, "onCreate")
        initializeLocationManager()
        try {
            mLocationManager!!.requestLocationUpdates(
                    LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL.toLong(), LOCATION_DISTANCE,
                    mLocationListeners[1])
        } catch (ex: java.lang.SecurityException) {
            Log.i(TAG, "fail to request location update, ignore", ex)
        } catch (ex: IllegalArgumentException) {
            Log.d(TAG, "network provider does not exist, " + ex.message)
        }

        try {
            mLocationManager!!.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, LOCATION_INTERVAL.toLong(), LOCATION_DISTANCE,
                    mLocationListeners[0])
        } catch (ex: java.lang.SecurityException) {
            Log.i(TAG, "fail to request location update, ignore", ex)
        } catch (ex: IllegalArgumentException) {
            Log.d(TAG, "gps provider does not exist " + ex.message)
        }

    }

    override fun onDestroy() {
        Log.e(TAG, "onDestroy")
        super.onDestroy()
        if (mLocationManager != null) {
            for (i in mLocationListeners.indices) {
                try {
                    mLocationManager!!.removeUpdates(mLocationListeners[i])
                } catch (ex: Exception) {
                    Log.i(TAG, "fail to remove location listners, ignore", ex)
                }

            }
        }
    }

    private fun initializeLocationManager() {
        Log.e(TAG, "initializeLocationManager")
        if (mLocationManager == null) {
            mLocationManager = applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        }
    }

    companion object {
        private val TAG = "BOOMBOOMTESTGPS"
        private val LOCATION_INTERVAL = 1000
        private val LOCATION_DISTANCE = 0f
    }
}

Вы можете заархивировать его с помощью Service and Alarm Manager, но будьте осторожны с этим, потому что, если вы установите высокий приоритет, вы собираетесь разрядить батарею телефона, с другой стороны, вам действительно нужно уведомлять местоположение каждую минуту? Это потому, что единственный способ увидеть значительное изменение местоположения пользователя, это путешествие на машине или поезде. Я только спрашиваю, потому что это будет зависеть от вашего приложения и требования отслеживания.

Хорошо. Создайте расширяющий класс Service, этот сервис будет содержать ваш класс слушателя Location (Fused Location Provider). Цель этого сервиса - периодически получать местоположение, что-то вроде этого

  public class LocationGetter extends Service {


    ......

    public class MyLocationListener implements GooglePlayServicesClient.ConnectionCallbacks,GooglePlayServicesClient.OnConnectionFailedListener,LocationListener, com.google.android.gms.location.LocationListener {

   //your fused Location provider code

    }

    ......

}

Затем создайте класс, расширяющий Broadcast Receiver, так, чтобы целью этого широковещательного Receiver было проверить, жива ли служба, если не перезапустить службу даже во время включения / выключения телефона

зарегистрировать приемник в своей активности, прослушивать трансляции, отключать приемник в зависимости от необходимости...

Для отслеживания местоположения каждые 10 минут (в зависимости от требований), пожалуйста, перейдите по этой ссылке, он работает нормально, без проблем

https://github.com/safetysystemtechnology/location-tracker-background

Чтобы получить обратный звонок на LocationChange

Определить интерфейс

public interface LocationCallback {
public void locationChanged(Location location);
}

Обратный звонок в вашей деятельности

public static LocationCallback callback;
public void getUserLocation() {

    callback = new LocationCallback() {
        @Override
        public void locationChanged(Location location) {
            Toast.makeText(getApplicationContext(), location.getLatitude() + "," + location.getLongitude(), Toast.LENGTH_SHORT).show();
        }
    };

    Intent service_intent = new Intent(this, GPSService.class);
    startService(service_intent);

}

Измените метод on LocationChange на

@Override
    public void onLocationChanged(Location location) {
        Log.e(TAG, "onLocationChanged: " + location);
        MapsActivity.callback.locationChanged(location);
        mLastLocation.set(location);
    }
Другие вопросы по тегам