首页 > 解决方案 > Android 后台位置更新 - Kitkat 和 Marshmallow 设备中不同数量的 LatLong

问题描述

我正在开发一个应用程序,它获取设备的当前纬度并将它们存储在一个新行的文件中。我在 kit kat 版本 4.4.4 和 marshmallow 版本 6.0.1 上运行我的应用程序。我把这两个设备都放在车里进行测试,然后在城市里兜了一圈。我注意到一个奇怪的输出,从 kit kat 生成的文件有 576 行意味着记录了 576 对纬度。但在棉花糖设备上生成的文件中只有 250 行 latlongs。据我所知,根据棉花糖中介绍的打盹模式的定义,手机只有在设备静止时才会进入打盹模式。但在我的情况下,该设备不是静止的,因为它在移动的汽车中。我很困惑。任何人都可以帮忙。

下面是我的后台服务类,没有文件保存代码。

public class GPSTrackerService extends Service {

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

@Override
public void onCreate() {
    super.onCreate();
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getApplicationContext());
    mSettingsClient = LocationServices.getSettingsClient(getApplicationContext());
    createLocationCallback();
    createLocationRequest();
    buildLocationSettingsRequest();

    new CountDownTimer(9900000,3000){

        @Override
        public void onTick(long l) {
            Log.d("BOSS_DK","On Tick");
        }

        @Override
        public void onFinish() {

        }
    }.start();
}

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


@TargetApi(Build.VERSION_CODES.M)
public void test(){
    Intent intent = new Intent();
    String packageName = getPackageName();
    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    if (pm.isIgnoringBatteryOptimizations(packageName))
        intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
    else {
        intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        intent.setData(Uri.parse("package:" + packageName));
    }
    startActivity(intent);
}

private LocationRequest mLocationRequest;
private LocationSettingsRequest mLocationSettingsRequest;
private FusedLocationProviderClient mFusedLocationClient;
private LocationCallback mLocationCallback;
private SettingsClient mSettingsClient;
// Start Fused Location services
protected void createLocationRequest() {
    // create the locatioon request and set parameters
    mLocationRequest = LocationRequest.create();
    mLocationRequest.setInterval(2000);  // will return location after every 5 seconds
    mLocationRequest.setFastestInterval(1000);  // fastest rate app can handle updates
    //mLocationRequest.setSmallestDisplacement(5);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}

private void buildLocationSettingsRequest() {
    // get current locations settings of user's device
    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest);
    builder.addLocationRequest(mLocationRequest);
    mLocationSettingsRequest = builder.build();

    startLocationUpdates();
}

private void startLocationUpdates() {
    // if settings are satisfied initialize location requests
    mSettingsClient.checkLocationSettings(mLocationSettingsRequest).addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
        @Override
        public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
            //locUpdates = true;
            // All location settings are satisfied.
            //noinspection MissingPermission - this comment needs to stay here to stop inspection on next line
            mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
        }
    })
            // if settings need to be changed prompt user
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    e.printStackTrace();
                }
            });
}

// stop location updates
private void stopLocationUpdates() {
    //locUpdates = false;
    mFusedLocationClient.removeLocationUpdates(mLocationCallback).addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
        }
    });
}

private void createLocationCallback() {
    mLocationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            super.onLocationResult(locationResult);
            List<Location> locations = locationResult.getLocations();
            /*if(locationResult.getLastLocation().hasAccuracy()) {
                setLatLong(locationResult.getLastLocation());
            }*/
            for(Location location : locations){
                setLatLong(location);
            }
        }
    };
}

// Set new latitude and longitude based on location results
public void setLatLong(Location location) {
    Log.d("BOSS_DK",String.valueOf(location.getLatitude())+","+String.valueOf(location.getLongitude()));
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.d("BOSS_DK","service destroyed");
}

}

标签: androidgpsandroid-6.0-marshmallowandroid-doze

解决方案


我想这是由于背景位置限制。状态:

如果您的应用程序在后台运行时依赖于实时警报或运动检测,则位置检索行为尤为重要。

系统区分前台和后台应用程序。如果以下任何一项为真,则认为应用程序处于前台:

它有一个可见的活动,无论活动是启动还是暂停。它有一个前台服务。另一个前台应用程序连接到该应用程序,或者通过绑定到它的一个服务,或者通过使用它的一个内容提供者。例如,如果前台应用程序绑定到另一个应用程序中的以下任何组件,则该其他应用程序被视为在前台: 输入法编辑器 (IME) 壁纸服务 通知侦听器 语音或文本服务 如果这些条件都不为真,应用程序被认为在后台。


推荐阅读