在安卓系统上获取当前GPS位置

4

我正在尝试通过GPS功能获取用户的当前位置,

编写了一个简单的类来实现LocationListener

public class LocationManagerHelper implements LocationListener {

    private static double latitude;
    private static double longitude;

    @Override
    public void onLocationChanged(Location loc) {
        latitude = loc.getLatitude();
        longitude = loc.getLongitude();
    }

    @Override
    public void onProviderDisabled(String provider) { }

    @Override
    public void onProviderEnabled(String provider) { }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        // TODO Auto-generated method stub

    }

    public static double getLatitude() {
        return latitude;
    }

    public static double getLongitude() {
        return longitude;
    }

}

通过一个简单的操作,我可以访问这些经度和纬度数值。

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    /** create a TextView and write Hello World! */
    TextView tv = new TextView(this);

    LocationManager mlocManager = 
                    (LocationManager) getSystemService(Context.LOCATION_SERVICE);

    LocationListener mlocListener = new LocationManagerHelper();

    mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
            mlocListener);

    if (mlocManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            tv.append("Latitude:- " + LocationManagerHelper.getLatitude()
                    + '\n');
            tv.append("Longitude:- " + LocationManagerHelper.getLongitude()
                    + '\n');
    } else {
        tv.setText("GPS is not turned on...");
    }

    /** set the content view to the TextView */
    setContentView(tv);

但它总是返回0.0作为结果。无法找出问题所在。


如果您不想编写太多代码并且需要一个更简单的接口,请使用https://github.com/delight-im/Android-SimpleLocation。 - caw
5个回答

19

位置更新实际上是异步的。这意味着API不会让您的调用线程等待直到有新的位置可用; 相反,您需要注册一个具有特定方法(callback)的观察者对象,每当计算出一个新位置时,该方法会被调用。

Android LocationManager API中,观察者是一个LocationListener对象,用于位置更新的主要回调是onLocationChanged()

以下是试图解释此点的示意图(希望这有助于您理解!)

Sequence diagram

因此,从您当前的代码开始:

  • 将mlocListener声明为Activity子类的成员变量
  • 在LocationListener实现中添加日志输出(Logcat行)
  • 保持其余的代码不变。
  • 如果尚未完成,请在清单中添加正确的权限(GPS需要FINE_LOCATION)。
  • 尝试让手机连接到互联网并靠近窗户,以便快速获取GPS定位(应该为~30秒)。

然后启动应用程序并观察日志记录中发生了什么。您会看到状态更改和位置更新不会立即在初始请求后发生,从而解释了为什么您的textview始终显示(0.0,0.0)。

更多信息:http://developer.android.com/guide/topics/location/obtaining-user-location.html


非常感谢您提供的超级详细的解释。 - Switch
好的,这个已经可以了。日志每30秒打印一次经纬度数值。现在我需要获取这些数值并更新UI。 - Switch

3

在onCreate()返回之后才能触发位置更新回调。如果将你的纬度/经度变量初始化为虚拟值,你可能会看到打印出这些值。

在onLocationChanged中放置一些日志,以便查看它是否被触发,然后了解一下Android应用程序如何处理回调和更新UI的相关知识。

还要确保你的应用程序在其清单文件中具有适当的权限。


2

获取mLocListener之后,请按照下面所示设置Criteria:

String mlocProvider;
Criteria hdCrit = new Criteria();
hdCrit.setAccuracy(Criteria.ACCURACY_COARSE);
mlocProvider = mlocManager.getBestProvider(hdCrit, true);

然后使用getLastKnownLocation:

tv.append("\n\nLocations (starting with last known):");
Location currentLocation = mlocManager.getLastKnownLocation(mlocProvider);

请确保在您的清单中具有以下内容
uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"
uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"

如果您正在使用模拟器 - 在Emulator Control选项卡中查找Location Controls。然后使用Manual标签设置经度和纬度,单击发送 - 当程序运行时,当您看到对onLocationChanged的调用时,请执行此操作。最好在onLocationChanged中记录日志。

顺便说一句,requestLocationUpdates中的参数设置为“... 0,0 ...” - 它会耗尽您的电池 - 我曾见过手机在6-8小时内死亡 - 将其更改为“... 30000、100...” - 第一个参数以毫秒为单位,另一个参数以米为单位。


如果您同时使用NETWORK_PROVIDER和GPS_PROVIDER,则需要仅请求ACCESS_FINE_LOCATION权限,因为它包括两个提供程序的权限。(ACCESS_COARSE_LOCATION权限仅包括NETWORK_PROVIDER的权限。) 您只需要添加一个权限(ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION),而不是同时添加两个权限。 - titusfx

0

当您在模拟器上检查时,它将返回0.0。您需要将位置传递给模拟器。 您可以从C:\ android-sdk_r06 \ android-sdk-windows \ tools \ ddms.bat文件中传递此内容。

在ddms中,有一个名为模拟器控件的选项卡。从那里,您可以将位置传递给模拟器。 尝试一下,希望能够起作用。


-3

并不是对那位先生问题的建设性回答。 - Tyler Durden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接