当前位置: 首页 > 知识库问答 >
问题:

在我使用Fused Location Client的android应用程序中,为什么我在使用此代码时会出现过时的GPS

有德业
2023-03-14

我的应用程序会显示一个导航图,如果当前的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。我应该考虑另一种方法吗?

共有3个答案

丌官高远
2023-03-14

我建议试着每隔一段时间更新一次

        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) {

            }
        });
闻飞跃
2023-03-14

问题在于,对于跟踪资产位置的应用程序,您没有使用推荐的方法。您已经尝试通过getCurrentLocation方法手动更新位置。事实上,getCurrentLocation方法是在不需要不断更新位置时使用的。例如,您只需要一个新的用户位置,用于注册、附近搜索等。

当您需要不断跟踪资产时,您应该通过Request estLocationUpdate方法侦听位置更新。根据官方推荐

适当使用位置信息可能对您的应用程序的用户有益。例如,如果您的应用程序帮助用户在步行或开车时找到路,或者如果您的应用程序跟踪资产的位置,它需要定期获取设备的位置。

这里我实现了一个完整的示例

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>

输出

确保您同时拥有精细和粗略位置权限

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

如果您想在最快的时间间隔内检索资产的位置,粗略定位和优先级高精度非常重要。以下设置也非常重要。

locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(12000);
locationRequest.setFastestInterval(2000);
locationRequest.setWaitForAccurateLocation(true);
locationRequest.setSmallestDisplacement(0); 
锺离良哲
2023-03-14

欢迎加入谷歌FusedLocationProvider的受害者俱乐部,我建议您与GPS提供商一起使用LocationManager。可用于请求活动中的位置

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获得GPS锁,当我打开谷歌地图时,GPS锁销立即出现。所以我做了一些研究,确信我发现了FusedLocationProvider的缺点,最后我使用了LocationManager,至于它为什么会这样,我遇到的一些问题是

  1. 它的融合了,这意味着它使用多个来源(WiFi、网络、GPS等),它将选择一个它认为合适的来源,或者在决定位置时混合使用所有来源
  2. FusedLocationProvider的最大卖点是它针对电池使用进行了优化,因此只要它能为您提供一个位置(通常是准确的,但并不总是准确的),如果它确定通话会给电池带来不必要的负载,它就不会影响硬件
  3. 它似乎也在做位置缓存,这可能是过时的位置修复的一个原因,在这个问题的评论中,一个用户分享了他们对这个案例的体验

FusedLocationProvider如何影响早期使用LocationManager的数据采集应用程序的定位精度

FusedLocationProvider由于缓存而导致问题

为什么LocationManager提供了更准确的位置

在某些情况下,FusedLocationProvider的性能如何

FusedLocationProvider如何提供不准确的结果,请参阅投票数第二高的答案

 类似资料: