[英]In my android app using Fused Location Client, Why am I getting stale GPS when using this code
我的应用程序显示导航图表,如果当前 GPS 位置可用,它也会显示。 我在一艘沿着已知路线移动的船上进行了测试。 有时会显示正确的位置。 有时我会得到一个旧的 GPS 位置,即使在要求重新阅读时也是如此。 有时它似乎卡在旧位置进行多次读取。 当这种情况发生时,我运行了谷歌地图,它似乎清除了错误,我又开始获得一个新的位置。
// try to look at GPS....
status1 = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
if (status1 != PackageManager.PERMISSION_GRANTED)
{ requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},10);
}
status2 = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
Object cancellationToken = null;
if (status2 == PackageManager.PERMISSION_GRANTED)
fusedLocationClient.getCurrentLocation(PRIORITY_HIGH_ACCURACY, (CancellationToken) cancellationToken)
.addOnSuccessListener(this, location -> // using lambda expression...
{ if (location != null)
{ GPSLatitude = location.getLatitude();
GPSLongitude = location.getLongitude();
gotGPS = true;
//if we have a location, and it is on chart, draw the blue dot....
谷歌地图比我更擅长阅读 GPS。 我是否应该考虑另一种方法。
欢迎来到遭受谷歌FusedLocationProvider
之手的人的FusedLocationProvider
,我建议您改用带有 GPS 提供程序的LocationManager
。 可用于在您的Activity
请求位置作为
fun getLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// do proper permissions handling
return
}
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
val gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
if (gpsEnabled) {
// Register for location updates
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0.0f, locationListener)
// Or get last known location
val location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
}
}
private val locationListener = LocationListener {
// Do something with the location
}
FusedLocationProvider
可以提供不准确的位置在某些情况下,我发现FusedLocationProvider
相当不准确,在最近的一次与您没有什么不同的经历中,我无法在我的应用程序中使用FusedLocationProvider
获得 GPS 锁定,当我打开谷歌地图时,GPS 锁定销立即出现。 所以我做了一些研究,果然我发现了FusedLocationProvider
的错误,我最终使用了LocationManger
,至于为什么它会这样表现,我遇到的一些问题是
Fused
,这意味着它使用多个来源(WiFi、网络、GPS 等),它将选择它认为合适的一个,或者在决定位置时选择所有来源FusedLocationProvider
的最大卖点是它针对电池使用进行了优化,因此只要它可以为您提供位置(通常是准确的,并非总是如此),如果它确定调用会给您带来不必要的负载,它就不会影响硬件电池FusedLocationProvider
引起的问题的链接 FusedLocationProvider
如何影响早期使用LocationManger
的数据收集应用程序的位置准确性
FusedLocationProvider
由于缓存而导致问题
问题是您没有对跟踪资产位置的应用程序使用推荐的方法。 并且您已尝试通过getCurrentLocation
方法手动更新位置。 事实上,当您不需要不断更新位置时,将使用getCurrentLocation
方法。 例如,您只需要一个用户的新位置,用于注册、附近搜索等。
当您需要不断跟踪资产时,您应该通过requestLocationUpdates
方法监听位置更新。 根据官方推荐
适当使用位置信息对您的应用程序用户有益。 例如,如果您的应用帮助用户在步行或开车时找到方向,或者您的应用跟踪资产位置,则需要定期获取设备的位置。
在这里我实现了一个完整的例子
package com.example.locationtracker;
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.os.Looper;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.example.locationtracker.databinding.ActivityMainBinding;
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.material.snackbar.Snackbar;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private boolean isTracking = false;
private FusedLocationProviderClient fusedLocationClient;
private LocationCallback locationCallback;
private LocationRequest locationRequest;
private LocationRecycleViewAdapter locationRecycleViewAdapter;
private final ArrayList<String> locations = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
com.example.locationtracker.databinding.ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.location.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
locationRecycleViewAdapter = new LocationRecycleViewAdapter(getApplicationContext(), locations);
binding.location.setAdapter(locationRecycleViewAdapter);
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(12000);
locationRequest.setFastestInterval(2000);
locationRequest.setWaitForAccurateLocation(true);
locationRequest.setSmallestDisplacement(0);
locationCallback = new LocationCallback() {
@Override
public void onLocationResult(@NonNull LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
System.out.println("New Location Received");
String loc = String.format("lat: %s, lon: %s", location.getLatitude(), location.getLongitude());
locations.add(loc);
locationRecycleViewAdapter.notifyDataSetChanged();
/*locationRecycleViewAdapter = new LocationRecycleViewAdapter(getApplicationContext(), locations);
binding.location.setAdapter(locationRecycleViewAdapter);*/
}
}
};
binding.fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!isTracking) {
Snackbar.make(view, "Starting Location Tracking", Snackbar.LENGTH_LONG)
.show();
startLocationUpdates();
} else {
Snackbar.make(view, "Stopping Location Tracking", Snackbar.LENGTH_LONG)
.show();
stopLocationUpdates();
}
}
});
}
@Override
protected void onResume() {
super.onResume();
if (isTracking) {
startLocationUpdates();
}
}
private static final int PERMISSION_REQUEST_CODE = 200;
private void startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_CODE);
return;
}
fusedLocationClient.requestLocationUpdates(locationRequest,
locationCallback,
Looper.getMainLooper());
isTracking = true;
}
private void stopLocationUpdates() {
fusedLocationClient.removeLocationUpdates(locationCallback);
isTracking = false;
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.locationtracker">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.LocationTracker">
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.LocationTracker.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
输出
确保您同时拥有FINE和COARSE位置权限
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
如果您想以最快的时间间隔检索资产的位置,则COARSE Location和PRIORITY_HIGH_ACCURACY非常重要。 以下设置也非常重要。
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(12000);
locationRequest.setFastestInterval(2000);
locationRequest.setWaitForAccurateLocation(true);
locationRequest.setSmallestDisplacement(0);
我建议尝试以间隔更新当前
if (ActivityCompat.checkSelfPermission(mActivity, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
log.w("Get locations:: "+ location.getLatitude());
newLocation(location);
// locationManager.removeUpdates(this);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
});
这是我现在正在使用的 Java 代码。
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// try to look at GPS....
status1 = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
if (status1 != PackageManager.PERMISSION_GRANTED)
{ requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},10);
}
status2 = checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
if (status2 == PackageManager.PERMISSION_GRANTED)
{ gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (gpsEnabled) // Register for location updates, each minute (60,000 milliseconds)
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000, 0.0f, locationListenerGPS);
LocationListener locationListenerGPS=new LocationListener() {
@Override
public void onLocationChanged(android.location.Location location) {
GPSLatitude = location.getLatitude();
GPSLongitude = location.getLongitude();
gotGPS = true;
reDraw();
//String msg="New Latitude: "+latitude + "New Longitude: "+longitude;
//Toast.makeText(mContext,msg,Toast.LENGTH_LONG).show();
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
};
///
based on Kotlin code from WOZ, it works well
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.