4

我想在我的应用程序中实现基于位置的功能。我一直在阅读,我发现自己有点困惑。

当谷歌搜索教程时,几乎每个结果都会返回一个使用 Android Location API 的示例。

但是,在阅读 android 开发人员指南时,他们声明了以下内容:

Google Play 服务位置 API 比 Android 框架位置 API (android.location) 更适合作为向您的应用添加位置感知的一种方式。如果您当前正在使用 Android 框架位置 API,强烈建议您尽快切换到 Google Play 服务位置 API。

安卓文档

所以这告诉我不要选择只实现位置监听器的更简单的方法。

所以我的问题是,这两者有什么区别?为什么我要使用一个而不是另一个?

我在哪里可以找到关于如何安全准确地正确访问 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();
}
}

然后我从我的活动中调用我的 LocationManager:

LocationManager locationManager = new LocationManager(this);
Location location = locationManager.getCoarseLocation();
//Use Location

我想创建一个助手类,我可以简单地从任何活动或片段中调用它。但是,当我运行以下命令时,构造函数执行成功。但是,我在回调中的断点都没有被命中。即使在 1 或 2 分钟后。

4

2 回答 2

5

Google Play Services Api 使用回调方法public void onConnected(Bundle bundle),仅在建立连接时调用。只有这样,LocationServices.FusedLocationApi.getLastLocation(googleApiClient)方法调用才能返回正确的Location.

您已经构建了一个辅助类来获取此位置,但您应该了解连接不是立即建立的。因此,简单地对辅助类或其方法进行异步调用可能会返回一个空对象,因为可能尚未建立连接。

您可以通过Location以下方式获取。

1) 广播位置并通过a接收,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 Services Location Api。只需在构造函数中的方法调用mGoogleApiClient.connect()之后添加方法调用buildGoogleApiClient();。您无需检查 Google Play 服务是否可用。

您还可以googleApiClient.connect();public void onConnectionSuspended(int i).

于 2015-04-01T08:48:17.633 回答
2

您需要致电:

mGoogleApiClient.connect()

除了您关于差异的问题:谷歌播放服务框架为您提供了一个“融合”的位置。对于 Android 框架,您应该使用 GPS 或 Wifi。您可以指定一个标准,但如果您需要定位用户位置,则 google play 服务是最佳选择。如果您需要一个非常精确的位置,例如 GPS,因为例如您的应用程序是一个导航器应用程序,那么最好直接使用 GPS。

于 2015-01-08T16:26:44.520 回答