谷歌播放服务或安卓定位服务

4
我希望在我的应用程序中实现基于位置的功能。我已经阅读了一些内容,但感到有些困惑。
当我搜索教程时,几乎每个结果都使用Android Location API作为示例。
然而,在阅读Android开发者指南时,他们声明如下:
“Google Play服务位置API比Android框架位置API(android.location)更受欢迎,作为向您的应用程序添加位置感知的方法。如果您目前正在使用Android框架位置API,则强烈建议您尽快切换到Google Play服务位置API。” Android Docs 这告诉我不要选择简单的实现位置监听器的路线。
因此,我的问题是,两者之间有什么区别?我为什么要使用其中一个而不是另一个?
在哪里可以找到一个合适的教程,以安全准确地访问Google Play服务位置API?
我已经尝试了这个(根据Android网站上的建议),但我的回调没有被调用。
public class LocationManager implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

private Context mContext;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;

public LocationManager(Context context) {
    mContext = context;
    //
    if (checkIfGooglePlayServicesAreAvailable()) {
        //Get Access to the google service api
        buildGoogleApiClient();
    } else {
        //Use Android Location Services
        //TODO:
    }
}

public Location getCoarseLocation() {
    if (mLastLocation != null) {
        return mLastLocation;
    } else return null;
}

private synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(mContext)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
}

private boolean checkIfGooglePlayServicesAreAvailable() {
    int errorCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext);
    if (errorCode != ConnectionResult.SUCCESS) {
        GooglePlayServicesUtil.getErrorDialog(errorCode, (MainActivity) mContext, 0).show();
        return false;
    }
    return true;
}


@Override
public void onConnected(Bundle bundle) {
    Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    if (location != null) {
        mLastLocation = location;
        Toast.makeText(mContext, location.getLongitude() + " , " + location.getLatitude() + " : " + location.getAccuracy(), Toast.LENGTH_LONG).show();
    }
}

@Override
public void onConnectionSuspended(int i) {
    Toast.makeText(mContext, "suspended", Toast.LENGTH_LONG).show();
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    Toast.makeText(mContext, connectionResult.toString(), Toast.LENGTH_LONG).show();
}
}

我然后从我的Activity中调用我的LocationManager:
LocationManager locationManager = new LocationManager(this);
Location location = locationManager.getCoarseLocation();
//Use Location

我想创建一个帮助类,可以在任何活动或片段中简单调用。然而,当我运行以下代码时,构造函数成功执行。但是回调函数中的断点都没有被触发,甚至等待1或2分钟后也是如此。


从我所看到的,根据你的代码判断,你没有像我记得我做的那样遵循Google指南... 你在哪里调用 requestLocationUpdates() 函数? - shkschneider
2
基本上,Google的位置API与Android的API相同,只是Google的API处理了所有不同的位置回调(GPS、网络、Wifi),因此您只需要担心是否获取到位置即可。 - tyczj
@shkschneider 我只是获取最后已知的位置:https://developer.android.com/training/location/retrieve-current.html,但我没有在Activity中实现它,而是将Activity引用传递给我的类。 - Zapnologica
2个回答

5
Google Play服务API使用回调方法public void onConnected(Bundle bundle),仅在建立连接时才会调用。只有这样,LocationServices.FusedLocationApi.getLastLocation(googleApiClient)方法调用才能返回正确的Location
您已经构建了一个助手类来获取此位置,但是您应该了解连接不会立即建立。因此,对于助手类或其方法的简单异步调用可能会返回空对象,因为可能尚未建立连接。
您可以按以下方式获取Location
1)广播位置并通过BroadcastReceiver接收它以从public void onConnected(Bundle bundle)中执行后续操作。这对我起作用了。
private boolean flag = false;

@Override
public void onConnected(Bundle connectionHint) {
    location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
    if (location != null && !flag) {
        flag = true;
        Intent intent = new Intent(LOCATION_BROADCAST_ACTION);
        intent.putExtra(INTENT_EXTRA_LOCATION, location);
        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
        Log.i(TAG, "Sending Location Broadcast");
        Log.i(TAG, location.toString());
    } else if (location == null){
        Toast.makeText(mContext, R.string.no_location_detected, Toast.LENGTH_LONG).show();
        Log.e(TAG, "No Location Detected");
    }
}

2) 在调用的Activity或Fragment中创建一个公共的Location对象,并在public void onConnected(Bundle bundle)方法中更新其值。

@Override
public void onConnected(Bundle connectionHint) {
    location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
    if (location != null) {
        MyActivity.location = location; // update the Location object of you caller activity or fragment
        Log.i(TAG, "location updated");
    }
}

此外,在创建完GoogleApiClient之后,您应该连接到Google Play服务位置API。只需在构造函数中的buildGoogleApiClient();方法调用后添加方法调用mGoogleApiClient.connect()即可。您不需要检查Google Play服务是否可用。
您还可以在public void onConnectionSuspended(int i)的实现中添加方法调用googleApiClient.connect();

2

您需要调用:

mGoogleApiClient.connect()

除了你关于差异的问题外:Google Play服务框架为您提供了一个“融合”位置。使用Android框架时,您应该使用GPS或Wi-Fi。您可以指定标准,但如果您需要位置用户位置,则Google Play服务是最好的选择。如果您需要像GPS这样非常精确的位置,因为例如您的应用程序是导航应用程序,那么最好直接使用GPS。

最好在哪里调用它?因为我想知道位置?还是在实例化我的LocationManager类时?根据您的描述,我明确地正在寻找Play服务。 - Zapnologica
1
我认为你在哪里创建对象。 - greywolf82
.connect() 方法需要多长时间才能完成连接?因为如果我在实例化对象时调用 .connect(),我需要在调用 getCoarseLocation() 时已经完成连接。有没有一种方法可以阻塞直到连接成功? - Zapnologica
1
你必须调用blockingConnect()函数,但是应该在后台线程上调用它,不要在UI线程上调用阻塞式调用。 - greywolf82

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