应用程序在后台获取 GPS 位置更新

Getting GPS location updates while app in the background

我有一个 android 应用程序可以跟踪客户位置并每 10 秒发送一次位置,但是,在 android O 中,位置更新将每小时更新几次,如关于 android O 中 gps 位置更新限制的文档。无论如何,为了克服这个问题,我使用了带有通知的前台服务,以便 gps 位置更新在 fusedLocation 中不断更新。 在那之后,我遇到了另一个问题,fusedLocation 中的速度和方向为零,因为它同时从网络提供商和 gps 提供商那里获取位置,当位置来自网络提供商时,速度和方向为零,这些信息对我很重要,并且我将我的位置服务切换到 LocationManager 而不是 fusedLocation,因此我只能确定 gps 提供者,因为 fusedLocation 中没有此功能。 但是我注意到,即使我为此目的使用前台服务,android O 中的 LocationManager 在后台也不会获取位置更新。如何获得在后台不断更新位置并仅使用 gps 提供商的解决方案?

我没有代码片段,我只是想讨论一下这个问题。

试试下面的代码行

在AndroidManifest.xml

中写入下面一行代码
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<application>
 <service
        android:name=".LocationTracker"
        android:stopWithTask="true"
        />
</application>

写下您想启动服务的代码行

LocationTracker.startLocationService(getApplicationContext());

在服务中编写以下代码class

public class LocationTracker extends Service{

private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000;
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 1000;
private static int DISPLACEMENT = 0;

private FusedLocationProviderClient mFusedLocationClient;
private LocationRequest mLocationRequest;
private SettingsClient mSettingsClient;
private LocationSettingsRequest mLocationSettingsRequest;
private LocationCallback mLocationCallback;
private String TAG = LocationTracker.class.getSimpleName();
private final int NOTIFICATION_ID = 9083150;
public static final String CHANNEL_ID = "CHANNEL_ID";
public static final String CHANNEL_ID_NAME = "CHANNEL_ID_NAME";

@Override
public void onCreate() {
    super.onCreate();
    try {
        if (Build.VERSION.SDK_INT >= 26) {
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID_NAME,
                    NotificationManager.IMPORTANCE_HIGH);
            channel.setSound(null, null);
            channel.setShowBadge(false);
            NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.deleteNotificationChannel(CHANNEL_ID);
            notificationManager.createNotificationChannel(channel);

            Notification notification = createNotification(getApplicationContext(),CHANNEL_ID,0);
            if (notification == null) {
                notification = new NotificationCompat.Builder(this, CHANNEL_ID).build();
            }
            startForeground(NOTIFICATION_ID, notification);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private Notification createNotification(Context context, String channelid,int type) {
    try {
        return new NotificationCompat.Builder(context,channelid)
                .setContentTitle("")
                .setContentText("")
                .setOnlyAlertOnce(true)
                .setOngoing(true)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setCategory(NotificationCompat.CATEGORY_SERVICE)
                .setVisibility(Notification.VISIBILITY_PRIVATE)
                .setSmallIcon(R.mipmap.ic_launcher)
                .build();

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


public void setLocationUpdateCallback() {
    try {
        mLocationCallback = null;
        mLocationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                Logger.i(TAG, "locationResult ==== " + locationResult);
            }
        };
    }catch (Exception e){
        e.printStackTrace();
    }
}

private void init() {
    try {
        setLocationUpdateCallback();
        mFusedLocationClient = null;
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        mSettingsClient = LocationServices.getSettingsClient(this);
        mLocationRequest = null;
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setSmallestDisplacement(DISPLACEMENT);

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

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

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

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

protected void startLocationUpdates() {
    mSettingsClient
            .checkLocationSettings(
                    mLocationSettingsRequest)
            .addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
                @SuppressLint("MissingPermission")
                @Override
                public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
                    Log.e(TAG, "LocationSettingsStatusCodes onSuccess");
                    mFusedLocationClient.requestLocationUpdates(mLocationRequest,
                            mLocationCallback, Looper.myLooper());
                }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    int statusCode = ((ApiException) e).getStatusCode();
                    switch (statusCode) {
                        case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                            Log.e(TAG, "LocationSettingsStatusCodes.RESOLUTION_REQUIRED");
                            mFusedLocationClient.requestLocationUpdates(mLocationRequest,
                                    mLocationCallback, Looper.myLooper());
                            break;
                        case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                            Log.e(TAG, "LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE");
                    }
                }
            });
}

public static void startLocationService(Context context) {
    try {
        Intent intent = new Intent(context, LocationTracker.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ContextCompat.startForegroundService(context, intent);
        } else {
            context.startService(intent);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

希望对您有所帮助