30

这就是我注册我的应用程序以接收位置更新的方式:

mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(Consts.ONE_MINUTE * 10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setFastestInterval(Consts.ONE_MINUTE);

Builder builder = new GoogleApiClient.Builder(context);
builder.addApi(ActivityRecognition.API);

mGoogleApiClient = builder.addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();

mGoogleApiClient.connect();

....
....

@Override
public void onConnected(Bundle connectionHint) {
   LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, locationUpdatespendingInent);
}

我的未决意图几乎在确切请求的时间间隔内在后台被调用......

到目前为止,一切都很好。

问题: 当 WIFI 被禁用/没有连接到任何网络,或者没有启用 3G/4G 网络数据时 - 融合的位置提供者不提供新的位置更新!

我的位置访问设置已打开,并检查了 GPS 卫星和 WI-FI 和移动网络位置。

更大的问题:有时在这种情况下,我确实通过未决意图收到位置更新回调,但它知道的最后一个位置(即使是一个小时前,而且我早已远离那个地方)

根据以下文件PRIORITY_BALANCED_POWER_ACCURACY

与 setPriority(int) 一起使用以请求“块”级别的准确性。块级精度被认为是大约 100 米的精度。使用这样的粗略精度通常会消耗更少的功率。

我希望融合的位置提供者在别无选择时会打开 GPS,或者如果他没有任何其他选择,至少不会提供新的位置更新。

另一个不可预测和令人不安的问题:

我改为PRIORITY_BALANCED_POWER_ACCURACY查看PRIORITY_HIGH_ACCURACY它的行为(24 小时)。所有间隔保持不变(更新之间的间隔为 10 分钟)。即使在没有网络/SIM 卡的手机中也确实收到了准确的位置,但是 - 电池很快耗尽了!当我查看电池历史时,我惊讶地发现GPS 收音机一直处于全传输模式!!!! 而且我还在我的日志中看到每分钟收到一次位置,即使我每十分钟请求一次位置(我没有任何其他安装的应用程序可以打开 GPS 来接收位置..)

我在几台设备(例如 Moto X 2013、HTC One X、Nexus 5)上注意到了这种行为,所有设备都带有最新的 Google Play 服务(版本 6.1.11)和 android KITKAT 4.4.4

我的应用程序很大程度上依赖于用户当前的位置,只要用户登录,就会在指定的时间间隔内定期接收位置更新,所以我不想使用该PRIORITY_HIGH_ACCURACY模式,以防止电池耗尽..

我的问题:

  • 如果融合位置提供者设置为接收更新PRIORITY_BALANCED_POWER_ACCURACY但没有任何 WI-FI 或手机信号塔信息,那么它是否应该使用 GPS?

  • 如果是这样,那我做错了什么?

  • 为什么我会收到不正确的误导性位置更新?(正如我在“更大的问题”部分中解释的那样..

  • PRIORITY_HIGH_ACCURACY为什么我使用该参数时GPS收音机一直打开而不是10分钟间隔打开?(我没有其他安装的应用程序可以更快地触发位置更新..)

4

4 回答 4

20

对于指定的问题,

1.如果融合位置提供商设置为接收更新PRIORITY_BALANCED_POWER_ACCURACY但没有任何 WI-FI 或手机信号塔信息,它是否应该使用 GPS?&
2.如果是这样,那我做错了什么?

显然,文档中的任何地方都没有明确指定唯一的来源。使用任PRIORITY一选项,即使通过代码,获取的“来源”location也是“融合”的。
[location.getProvider()返回:“fused”]
我看到 GPS 仅在LocationRequest具有 PRIORITY_HIGH_ACCURACY 时使用。所以它在其他条件下不使用 GPS。

4.为什么我使用 PRIORITY_HIGH_ACCURACY 参数时 GPS 收音机一直打开而不是 10 分钟间隔打开?(我没有其他安装的应用程序可以更快地触发位置更新..)

最快间隔已设置为 1 分钟。据我了解,当最快间隔的值的持续时间短于 setInterval 的值时, setFastestInterval优先于setInterval 。
在您的情况下,1 分钟对 10 分钟。
关于没有其他已安装的触发位置更新的应用程序,它只是作为示例给出,并没有明确指定只有这种情况。

这控制您的应用程序接收位置更新的最快速率,在某些情况下(例如,如果其他应用程序正在触发位置更新),这可能比 setInterval(long) 更快。

因此,发生的情况是PRIORITY_HIGH_ACCURACY,它通过使用 GPS(有点独占)请求location最快的间隔设置 - 1 分钟。

3.为什么我会收到不正确的误导性位置更新?(正如我在“更大的问题”部分中解释的那样..

还需要检查pendingIntent机制的代码。尽管可能需要注意一些事项:
您可以添加一个location.getTime()以确保和验证获得位置的时间。如果范围内没有 wifi 蜂窝塔并被使用,它很可能不会被更新PRIORITY_BALANCED_POWER_ACCURACY
首先,在调用“lastKnown”时使用的块级位置精度无济于事。

电池消耗是由于 GPS 和 1 分钟更新的组合。尝试将最快的间隔设置为 5 或 10 分钟,如果这适合您的实施,但PRIORITY_BALANCED_POWER如果您需要绝对准确的位置,则可能无济于事。我通常会检查获得的位置,onLocationChanged并根据它在 LocationRequest 中切换优先级。当然,它通常有助于获得位置,除非我在没有 GPS 视线的建筑物内,并且 Wifi 网络已关闭。

于 2014-10-08T06:40:10.813 回答
4

我建议您以每 10 分钟一次的火警警报的方式使用AlarmManagerFusedLocationProvider一起使用,AlarmManager以便开始位置更新。

获得更新的位置后,断开位置客户端。您不需要通过在 中设置间隔时间来使其一直运行LocationRequest,而是可以通过使用在每个时间间隔上调用该进程AlarmManager

在这种机制下,您将获得以下好处,可以解决您的问题:

  • GPS 无线电在检索位置时只会保持打开几秒钟,因为您将在获得第一次位置更新后断开连接。因此 GPS 收音机不会一直保持打开状态,因此可以节省电池。
  • 您将能够每 10 分钟获得一次新位置,而不会弄乱旧位置或其他东西。

我希望它会有所帮助。

于 2014-10-10T11:36:52.643 回答
3

手机信号塔覆盖了几英里的区域,因此它们不是获取位置的最佳选择。在处理位置时查看位置精度。

@Override
public void onLocationChanged(Location location) {
    //it happens
    if (location == null) {
        return;
    }
    // all locations should have an accuracy
    if (!location.hasAccuracy()) {
        return;
    }
    // if its not accurate enough don't use it
    // this value is in meters
    if (location.getAccuracy() > 200) {
        return;
    }
}

您可以在网络状态上放置一个广播接收器,当没有连接时,您可以使用 priority_high_accuracy 重新启动您的位置提供程序,这将仅在用户启用 GPS 时使用 GPS,否则它会退回到 wifi 和手机信号塔。

<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>

/** Checks whether the device currently has a network connection */

private boolean isDeviceOnline() {
    ConnectivityManager connMgr = (ConnectivityManager) activity
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
    if (networkInfo != null && networkInfo.isConnected()) {
        return true;
    }
    return false;
}
于 2014-10-07T20:29:52.360 回答
0

要更新 GPS 坐标,您也可以使用 GPS 和 WI-FI 提供商。对于位置的更新,以及最小距离参数。我将为您提供小型 GPS 服务示例。

答案:

1) PRIORITY_BALANCED_POWER_ACCURACY使用 GPS。

2) 使用 GPS 和 WI-FI 检测位置。

3) PRIORITY_BALANCED_POWER_ACCURACY 可能是因为该地区没有 WI-FI。

代码示例:

public class GPSservice extends Service implements LocationListener {


    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 2;

    private static final long MIN_TIME_BW_UPDATES = 1000 * 1;

    double latitude, longitude;

    boolean isGPSEnabled = false;

    boolean isNetworkEnabled = false;

    boolean canGetLocation = false;

    Location location;

    protected LocationManager locationManager;

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


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        getLocation();

        return super.onStartCommand(intent, flags, startId);
    }


    @Override
    public void onLocationChanged(Location location) {
        new LocationReceiver(location, getApplicationContext());
    }


    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }

    public Location getLocation() {
        try {
            locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

            // getting GPS status
            isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled) {
                Log.d("Network", "NO network");
            } else {
                this.canGetLocation = true;
                if (isNetworkEnabled) {
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("Network", "Network");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }
                if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPS Enabled", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }

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

        return location;
    }
}
于 2014-10-05T08:09:42.883 回答