【问题标题】:How can I get the current gps location every time a function is called?每次调用函数时如何获取当前 gps 位置?
【发布时间】:2018-12-04 14:01:51
【问题描述】:

我想要做的是每次调用函数时获取位置纬度和经度。据我所知,最好的方法是将位置更新保留几秒钟以获取正确的修复,然后将其禁用,但我无法使其在我的应用中运行。

到目前为止,我所做的是在每次调用 displayData 函数时获取手机的最后一个已知位置,但我无法克服尝试更改为时出现的所有错误请求位置更新。我在这里所做的是调用 displayData 函数,当有来自蓝牙设备的传入数据时,以获取位置并将数据+位置写入文件。

谁能帮助我,因为所有指南都显示了如何在位置更新时触发某些东西,但我不想这样做。 我只是想要一个定期的正确位置...

private void displayData(final byte[] byteArray) {
try {

    mFusedLocationClient.getLastLocation()
            .addOnSuccessListener(this, new OnSuccessListener<Location>() {
                @Override
                public void onSuccess(Location location) {
                    // Got last known location. In some rare situations this can be null.

                    if (byteArray != null) {
                        String data = new String(byteArray);
                        tv.setText(n/2 + " measurements since startup...");
                        n += 1;

                        if (location != null) {
                            double lat = location.getLatitude();
                            double lng = location.getLongitude();
                            latitude = String.valueOf(lat);
                            longitude = String.valueOf(lng);
                        }

                        try
                        {
                            FileWriter fw = new FileWriter(textfile,true); //the true will append the new data
                            if (writeDate()) {
                                fw.write("\n");
                                fw.write(stringDate);
                                fw.write(data); //appends the string to the file
                            }
                            else {
                                fw.write(data); //appends the string to the file
                                fw.write(" - ");
                                fw.write(latitude);
                                fw.write(",");
                                fw.write(longitude);
                            }
                            fw.close();
                        }
                        catch(IOException ioe)
                        {
                            System.err.println("IOException: " + ioe.getMessage());
                        }


                        // find the amount we need to scroll. This works by
                        // asking the TextView's internal layout for the position
                        // of the final line and then subtracting the TextView's height
                        final int scrollAmount = tv.getLayout().getLineTop(
                                tv.getLineCount())
                                - tv.getHeight();
                        // if there is no need to scroll, scrollAmount will be <=0
                        if (scrollAmount > 0)
                            tv.scrollTo(0, scrollAmount);
                        else
                            tv.scrollTo(0, 0);
                    }
                }
            });

} catch (SecurityException e) {
    // lets the user know there is a problem with the gps
}
}

【问题讨论】:

  • 也许您可以将获取/维护位置和调用displayData() 解耦。只需为最新位置设置一个变量并在displayData() 中使用它。然后担心根据绝对需要的准确度以及设备应该移动的速度分别维护最新的位置。如果速度很高并且位置需要准确,您可能只需请求位置更新并保持它们的出现。否则,您可以通过请求更新、接收一个或几个然后取消它们以节省电池来定期更新。
  • 这可能是合理的,因为获取位置是异步的,而您的 displayData() 显然应该是同步的,而不是等待其他一些操作完成。但您更了解自己的应用。
  • 谢谢马库斯。我也喜欢你的方法。如果我想节省电池,我可以设置一个等于 displayData 重复周期的 minTime 值(更新位置),我会没事的,不是吗?如果我在 displayData “外部”获取更新的位置,我什至可以保留此代码并使用最后一个非常准确的已知位置,对吧?
  • 是的,“最后一个已知位置”将与onLocationChanged() 回调返回的最新位置一样好(相同)。从理论上讲,如果其他一些应用程序也请求位置更新,它可能会有所不同。甚至可能使用“更糟糕”的设置。存储在onLocationChanged() 中收到的值可能是一种更安全的方式。我还没有实际测试过这种情况。

标签: java android geolocation


【解决方案1】:

以下是我对您的问题的理解:

  • 您希望按需 GPS 定位,但是:
  • 您不希望 GPS 持续运行,并且:
  • 您接受 GPS 必须在短时间内运行

尽量不要考虑“返回手机当前位置的函数”,因为这意味着它是一个简单的同步操作,可以在不阻塞的情况下提供答案。我们不能在这里这样做。

相反,我建议您将其更多地视为FSM,因为在您调用displayData() 和开始变得真实之间您需要任意时间(可能是几秒钟,可能更多) - 时间 GPS 修复。换句话说,displayData() 不会直接生成位置;它将启动一系列事件,最终导致您获得位置。

您必须承诺使用requestLocationUpdates()(或类似方法):

private void displayData(final byte[] byteArray) {
    //This call turns the GPS on, and returns immediately:
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new LocationListener() {

        //This function gets called some time after displayData() returns (possibly
        //*way* after). It executes on the UI thread.
        public void onLocationChanged(Location location) {
            locationManager.removeUpdates(this); //Shut down the GPS

            //(Execute the remainder of your onSuccess() logic here.)

            //Now our state machine is complete, and everything is cleaned up.
            //We are ready for the next call to displayData().
        }

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

        public void onProviderEnabled(String provider) {}

        public void onProviderDisabled(String provider) {}
    );
}

这样,

  • 我们不会阻塞 UI 线程(displayData() 立即返回)
  • 状态机最终收敛到一个答案(假设 GPS 功能正常)
  • 获得所需信息后,GPS 将关闭

您可能需要考虑对此方案的一些改进:

  • 如果在前一个请求解决之前调用 displayData(),避免重复调用 requestLocationUpdates() 的方法
  • 处理onSuccess() 方法中引用的 UI 元素不再可用的情况,因为在 GPS 请求“进行中”期间 Activity 拥有onDestroy()'d
  • 如果您需要清理等,取消正在进行的请求。

【讨论】:

  • 非常感谢。我会尝试并告诉您,但在您的示例中,我认为我们只执行了一次 onLocationChanged(这将距离实际位置很多米,不是吗?)。或者我是否遗漏了一些东西,并且即使一次做得好,onLocationChanged 也会返回?如果没有,我希望在编写位置之前让 onLocationChanged 运行几次(几秒钟)以进行更好的修复,所以我想我可以尝试 Markus 在他的评论中建议的方法?
  • 我没有测试过这段代码。但是由于指定了 GPS_PROVIDER,我认为它不会给你一个过时的修复。第一次onLocationChanged()触发,应该是高精度的。但是你的建议(比如在你打电话给removeUpdates() 之前数到 2)或@markus-kauppinen 的建议也是非常有效的做事方式。
【解决方案2】:

我遵循 Markus Kauppinen 的方法,要求以适合我的应用程序的时间间隔更新位置,然后在有来自蓝牙的传入数据时使用获取最后一个已知位置。所以我只是在我的活动中添加了以下内容:

    LocationRequest mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(30000);
    mLocationRequest.setFastestInterval(10000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    LocationCallback mLocationCallback = new LocationCallback();



// Register the listener with the Location Manager to receive location updates
    try {
        mFusedLocationClient.requestLocationUpdates(mLocationRequest,
                mLocationCallback,
                null /* Looper */);

    }
    catch (SecurityException e) {
        // lets the user know there is a problem with the gps
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-01
    • 2011-02-11
    • 2016-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多