Google Play 服务或 Android 定位服务

Posted

技术标签:

【中文标题】Google Play 服务或 Android 定位服务【英文标题】:Google Play Services or Android Location Services 【发布时间】:2015-03-06 19:50:19 【问题描述】:

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

在谷歌上搜索教程时,几乎每个结果都会返回一个使用 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();


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

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

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

【问题讨论】:

据我所知,根据您的代码判断,您没有像我记得的那样遵循 Google 指南...您在哪里 requestLocationUpdates() 基本上 google 位置 API 是相同的,除了 google 的 android 处理所有不同的位置回调(GPS、网络、Wifi),所以您只需要担心是否获得位置 @shkschneider 我只是得到了最后一个已知位置:developer.android.com/training/location/retrieve-current.html 但是我没有在 Activity 中实现它,我正在将 Activity 引用传递给我的班级。 【参考方案1】:

Google Play Services 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 Services Location Api。只需在构造函数中的buildGoogleApiClient(); 方法调用之后添加方法调用mGoogleApiClient.connect()。您无需检查 Google Play 服务是否可用。

您还可以在 public void onConnectionSuspended(int i) 的实现中添加方法调用 googleApiClient.connect();

【讨论】:

【参考方案2】:

您需要致电:

mGoogleApiClient.connect()

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

【讨论】:

最好在哪里称呼它?正如我想要的位置?或者在实例化我的 LocationManager 类时?根据您的描述,我正在寻找播放服务。 我想你在哪里创建对象。 .connect() 需要多长时间?因为如果我打电话。当我实例化对象时连接。我需要在我打电话给getCoarseLocation() 之前连接它有什么方法可以阻止它直到它连接? 当然你必须调用blockingConnect()但是你应该在后台线程上调用它,不要在UI线程上调用阻塞调用

以上是关于Google Play 服务或 Android 定位服务的主要内容,如果未能解决你的问题,请参考以下文章

查找位置:Google Play 位置服务或 Android 平台位置 API

Google Play 游戏,“已保存的游戏”已弃用?

Android 推送通知 - Google Play

如何将国产android机添加到google play?

您好google play 服务无法运行,怎么办?

如何使用 Facebook 好友制作 Android 多人游戏? (Google Play 游戏服务仅使用 G+)