FusedLocationProviderClient 未发送位置更新

6

我尝试在Android上使用新的简化位置API(在GPS 11.0中引入)。我编写了一个实现位置API的服务。但它只会触发并发送位置几秒钟(仅2次)。

    public class LocationService extends Service {
    public static final String TAG = makeLogTag("LocationService");

    private static final float LOCATION_TRACKING_MIN_DISTANCE = 15f;
    private static final float ACCEPTED_ACCURACY = 50f;

    private final IBinder mBinder = new LocalBinder();

    // fused location api
    private FusedLocationProviderClient mFusedLocationClient;
    private LocationRequest mLocationRequest;
    private LocationCallback mLocationCallback;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "onCreate");
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        createLocationCallback();
        createLocationRequest();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand");
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            stopSelf();
            return START_NOT_STICKY;
        }

        getLastKnownLocation();
        startPeriodicLocationUpdate();

        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopPeriodicLocationUpdate();
        Log.i(TAG, "onDestroy - Estou sendo destruido ");
    }

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

    private void getLastKnownLocation() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        mFusedLocationClient.getLastLocation()
                .addOnCompleteListener(task -> {
                    if (task.isSuccessful() && task.getResult() != null) {
                        Location lastLocation = task.getResult();
                        storeLocation(lastLocation);
                    }
                });
    }

    private void createLocationRequest() {
        mLocationRequest = new LocationRequest()
                .setInterval(TimeUnit.SECONDS.toMillis(Params.getAgentLocationTrackingUpdateInterval()))
                .setFastestInterval(TimeUnit.SECONDS.toMillis(Params.getAgentLocationTrackingUpdateInterval()))
                .setExpirationDuration(TimeUnit.SECONDS.toMillis(10))
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    private void createLocationCallback() {
        mLocationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                Location location = locationResult.getLastLocation();
                if (location != null) {
                    storeLocation(location);
                }

                Log.i(TAG, "locationResult start");
                for (Location location1 : locationResult.getLocations()) {
                    Log.i(TAG, "locationResult location " + location1.getLatitude() + " " + location1.getLongitude() + " " + location1.getAccuracy() + " " + location1.getProvider());
                }
                Log.i(TAG, "locationResult stop");
            }
        };
    }

    private void startPeriodicLocationUpdate() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }

        Log.i(TAG, "periodic update");
        mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
    }

    private void stopPeriodicLocationUpdate() {
        mFusedLocationClient.removeLocationUpdates(mLocationCallback)
                .addOnCompleteListener(task -> LOGI(TAG, "removed location updates!"));
    }

    private void storeLocation(Location location) {
        Log.i(TAG, "periodic location " + location.getLatitude() + " " + location.getLongitude() + " " + location.getAccuracy() + " " + location.getProvider());
        if (location.getAccuracy() <= ACCEPTED_ACCURACY) {
            Log.i(TAG, "storeLocation: " + "saved!");
            AgentLocationVo agentLocation = new AgentLocationVo();
            agentLocation.setDate(DateHelper.getDate(location.getTime()));
            agentLocation.setLatitude(location.getLatitude());
            agentLocation.setLongitude(location.getLongitude());
            agentLocation.setAccuracy(location.getAccuracy());
            agentLocation.setSyncState(SyncState.NOTUPLOADED);
            if (!AgentLocationDao.isAgentLocationExist(agentLocation))
                AgentLocationDao.insert(agentLocation);
        }
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        Log.i(TAG, "onTaskRemoved: ");
        stopSelf();
        JobDispatcher.stopSendLocationJob(getApplicationContext()); // TODO: 04/07/17 not the best place for it
    }

    public static void start(Context context) {
        context.startService(new Intent(context, LocationService.class));
    }

    public static void stop(Context context) {
        context.stopService(new Intent(context, LocationService.class));
    }

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
        public LocationService getService() {
            // Return this instance of LocationService so clients can call public methods
            return LocationService.this;
        }
    }
}

以下是我用来创建服务的资源: https://android-developers.googleblog.com/2017/06/reduce-friction-with-new-location-apis.html

https://github.com/googlesamples/android-play-location/blob/master/LocationUpdates/app/src/main/java/com/google/android/gms/location/sample/locationupdates/MainActivity.java

https://blog.stylingandroid.com/locationservices/

我甚至尝试使用了带有Pending Intent版本的方法,但结果相同。即使应用程序在前台运行。


你好,我该如何让这个服务在前台时与我的活动进行通信呢?比如说,我想在每次位置回调被调用时更新地图。 - Ralph
1个回答

3
原因在于这行代码。
  .setExpirationDuration(TimeUnit.SECONDS.toMillis(10))

@bkach LocationRequest 在 10 秒后过期。 - android_dev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接