本文概述
- 包” android.location”
- Google定位服务API
- 本文总结
文章图片
在本文中, 我们将构建一个简单的Android应用程序, 以使用Android的Google定位服务API确定用户的纬度和经度。开发Android应用程序时, 有两种获取用户位置的方法。
包” android.location” 自从首次引入Android以来, ” android.location” 包已可用, 它使我们能够访问位置服务。这些服务允许应用程序获取设备地理位置的定期更新。
该软件包提供了两种获取位置数据的方法:
- LocationManager.GPS_PROVIDER:使用卫星确定位置。根据条件, 此提供程序可能需要一段时间才能返回位置信息。
- LocationManager.NETWORK_PROVIDER:根据附近的基站和WiFi接入点的可用性确定位置。这比GPS_PROVIDER快。
该软件包提供的API相当底层, 并且要求应用程序的开发人员处理更精细的细节, 以确定何时请求位置数据并以优化的方式安排对API的调用。为了改善开发人员使用基于位置的系统服务的体验并简化开发可识别位置的应用程序的过程, Google引入了一种使用Google Play服务请求用户位置的新方法。它提供了更简单的API, 具有更高的准确性, 低功耗的地理围栏等等。
Google定位服务API Google定位服务API(也称为FusedLocationProviderApi)是Google推荐的获取用户位置的方法。它可以根据我们的需求提供最佳的准确性。与上一个相比, 使用此API的一些优点是:
- 简便性:与以前的API不同, 你不再需要与多个提供程序打交道。相反, 你可以指定高层需求, 例如”
高精度”
或”
低功耗”
, 这将采用合适的方法。
- 可用性:可让你的应用立即访问最近的最佳已知位置。通常, 此信息是随时可用的, 你只需要索取即可。
- 节能:最大限度地减少应用程序的功耗。
- 多功能性:满足广泛的需求, 从前景使用-需要高度精确的位置数据, 到后台使用-仅需要定期位置更新, 而对功率的影响却可以忽略不计。
Android Studio应该使我们的工作变得异常简单。但是, 我们需要首先配置构建脚本并添加Google Play服务作为此应用程序的依赖项。这可以通过如下修改” build.gradle” 文件来完成:
dependencies {
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.google.android.gms:play-services:6.5.87' // Add this line
}
在撰写本文时, 可用的最新版本的Google Play服务是6.5.87。开始之前, 请确保始终检查可用的最新版本。如果以后会出现较新的版本, 并且你决定为自己的项目进行更新, 请针对所支持的所有Android版本测试所有与位置相关的功能。
在这一点上, 我们应该能够开始为我们的应用程序做实际的工作。
请求权限, 配置AndroidManifest.xml Android具有特定的安全功能, 可以防止任何任意应用程序请求精确的用户位置。为了解决这个问题, 我们需要编辑” AndroidManifest.xml” 并添加此应用程序所需的权限:
<
uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
在进行此操作时, 我们还应该定义用于此应用程序的Google Play服务的版本:
<
meta-data android:name="com.google.android.gms.version"
android:value="http://www.srcmini.com/@integer/google_play_services_version" />
检查Google Play服务的可用性 在使用Google Play服务提供的功能之前, 我们必须检查该设备是否已安装Google Play服务, 并且该版本是否为我们打算使用的版本(6.5.87)。
private boolean checkGooglePlayServices(){
int checkGooglePlayServices = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(mContext);
if (checkGooglePlayServices != ConnectionResult.SUCCESS) {
/*
* Google Play Services is missing or update is required
*return code could be
* SUCCESS, * SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED, * SERVICE_DISABLED, SERVICE_INVALID.
*/
GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, mContext, REQUEST_CODE_RECOVER_PLAY_SERVICES).show();
return false;
} return true;
}
此方法将检查Google Play服务, 并且在设备未安装Google Play服务的情况下(这种情况很少见, 但我见过这种情况), 它将打开一个对话框并显示相应的错误, 并邀请用户安装/更新Google Play商店中的Google Play服务。
文章图片
用户完成” GooglePlayServicesUtil.getErrorDialog()” 提供的解析后, 将触发回调方法” onActivityResult()” , 因此我们必须实现一些逻辑来处理该调用:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_RECOVER_PLAY_SERVICES) {
if (resultCode == RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!mGoogleApiClient.isConnecting() &
&
!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
} else if (resultCode == RESULT_CANCELED) {
Toast.makeText(mContext, "Google Play Services must be installed.", Toast.LENGTH_SHORT).show();
finish();
}
}
}
访问Google API 要访问Google API, 我们只需要再执行一个步骤:创建一个GoogleApiClient实例。 Google API客户端提供了所有Google Play服务的通用入口点, 并管理用户设备和每个Google服务之间的网络连接。我们在这里的第一步是启动连接。我通常从活动的” onCreate” 方法调用此代码:
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
通过链接一系列方法调用, 我们指定了回调接口实现和我们要使用的Location Service API。当与Google Play服务的连接成功, 失败或被挂起时, 接口实现(在本例中为” this” )将收到对异步” connect()” 方法的响应。添加此代码后, 我们的” MainActivity” 应如下所示:
package com.bitwoo.userlocation;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
public class MainActivity extends ActionBarActivityimplements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { private static int REQUEST_CODE_RECOVER_PLAY_SERVICES = 200;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (checkGooglePlayServices()) {
buildGoogleApiClient();
}
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu;
this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}return super.onOptionsItemSelected(item);
} private boolean checkGooglePlayServices() {int checkGooglePlayServices = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
if (checkGooglePlayServices != ConnectionResult.SUCCESS) {
/*
* google play services is missing or update is required
*return code could be
* SUCCESS, * SERVICE_MISSING, SERVICE_VERSION_UPDATE_REQUIRED, * SERVICE_DISABLED, SERVICE_INVALID.
*/
GooglePlayServicesUtil.getErrorDialog(checkGooglePlayServices, this, REQUEST_CODE_RECOVER_PLAY_SERVICES).show();
return false;
}return true;
} @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_RECOVER_PLAY_SERVICES) {if (resultCode == RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!mGoogleApiClient.isConnecting() &
&
!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
} else if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Google Play Services must be installed.", Toast.LENGTH_SHORT).show();
finish();
}
}
} protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
} @Override
public void onConnected(Bundle bundle) { } @Override
public void onConnectionSuspended(int i) { } @Override
public void onConnectionFailed(ConnectionResult connectionResult) { }
}
然后, 在我们的” onStart” 方法中, 我们调用” connect” 方法, 并等待” onConnected” 回调方法被调用:
@Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}}
” onConnected” 方法将如下所示:
@Override
public void onConnected(Bundle bundle) { mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {Toast.makeText(this, "Latitude:" + mLastLocation.getLatitude()+", Longitude:"+mLastLocation.getLongitude(), Toast.LENGTH_LONG).show();
}}
连接Google Play服务时会触发此回调, 这意味着我们应该拥有最近的已知位置。但是, 此位置可以为空(很少见但并非不可能)。在这种情况下, 我建议你侦听位置更新, 这将在后面介绍。
收听位置更新 调用” getLastLocation” 后, 你可能需要向融合位置提供者请求定期更新。根据你的应用程序, 此时间段可能短或长。例如, 如果你要构建一个在用户开车时跟踪其位置的应用程序, 则需要间隔很短的时间监听更新。另一方面, 如果你的应用程序要与他的朋友共享用户位置, 则可能只需要偶尔请求一次位置。
创建请求非常简单-你可以在” onCreate” 方法内调用此方法:
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(20000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
我们实例化一个新的LocationRequest对象。将时间间隔设置为20秒(20000毫秒)。此外, 我们将限制更新速率设置为5秒。这告诉API每20秒(最好)提供一次更新, 但是如果5秒钟内有可用的更改, 它也应该提供。最后, 我们将优先级设置为” PRIORITY_HIGH_ACCURACY” , 以及其他可用的优先级选项:PRIORITY_BALANCED_POWER_ACCURACY, PRIORITY_LOW_POWER, PRIORITY_NO_POWER。
建立请求后, 就可以在触发” onConnected()” 方法之后开始侦听位置更新:
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
现在剩下的就是实现回调方法以满足LocationListener接口:
public class MainActivity extends ActionBarActivity implements
ConnectionCallbacks, OnConnectionFailedListener, LocationListener { // ... @Override
public void onLocationChanged(Location location) {
mLastLocation = location;
Toast.makeText(this, "Latitude:" + mLastLocation.getLatitude()+", Longitude:"+mLastLocation.getLongitude(), Toast.LENGTH_LONG).show();
}}
文章图片
停止听更新 当你不再需要更新或用户退出应用程序时, 明确停止监听更新非常重要。应该从” onPause” 回调中调用以下方法:
protected void stopLocationUpdates() {
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
}
…并断开Goog??le API的连接:
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
}
本文总结 如你所见, 在Android中实现位置感知应用程序的基本思想非常简单。此外, 借助易于使用和易于理解的可用API, 为Android构建基于位置的基本应用程序应该是轻而易举的事。我们在此处构建的小样本应用程序旨在证明这一点。你可以在GitHub上找到完整的源代码。请注意, 为简单起见, 应用程序未处理” onConnectionFailed” 回调方法。
【Android开发人员的Google定位服务API指南】希望本教程可以帮助你开始使用Google Location Services API。
推荐阅读
- iOS 8应用程序扩展教程
- 勇敢面对Android开发人员,新的Android编译器即将发布
- 通过SMTP(Gmail)示例类在Android上发送电子邮件
- 模仿ASP.NET和#039经典ASP中的AppendFormat方法
- 将Gmail迁移到googleapps的imapsync脚本
- 使用applescript创建并发送电子邮件
- 使用Intent从Android发送电子邮件
- 基于adb的Android端口转发
- Android警报对话框