問題描述
我想構建一個以獲取用戶當前位置為中心的應用,然后通過 Google Places API找到他/她附近的興趣點(如酒吧、餐館等)>.
I want to build an app that centers around getting the user's current location and then find points of interest(such as bars,restaurants,etc) that are close to him/her via the Google Places API.
在網(wǎng)上搜索起點時,我發(fā)現(xiàn)了一些使用 LocationManager
類的教程和其他一些使用 Google Play 服務 來查找用戶的教程位置.
Upon searching the web for a place to start I came across some tutorials that use the LocationManager
class and some others that use Google Play Services in order to find the users location.
乍一看他們都做同樣的事情,但由于我是新手,所以我有點困惑,我不知道哪種方法最適合我的需要.所以,我想問你:
On first sight both of them do the same thing, but since I am new to this I got a little confused and I don't know which method suits my needs the best. So, I want to ask you :
這兩種查找位置的方法(如果有的話)有什么區(qū)別?
推薦答案
Android 上的用戶位置
在 Android 上獲取用戶的位置比在 iOS 上要簡單一些.要開始混淆,有兩種完全不同的方法可以做到這一點.第一個是使用來自 android.location.LocationListener
的 Android API,第二個是使用 Google Play Services API com.google.android.gms.location.LocationListener
.讓我們來看看它們.
Getting the user’s location on Android is a little less straightforward than on iOS. To start the confusion, there are two totally different ways you can do it. The first is using Android APIs from android.location.LocationListener
, and the second is using Google Play Services APIs com.google.android.gms.location.LocationListener
. Let’s go through both of them.
Android 的位置 API
Android 的位置 API 使用三個不同的提供程序來獲取位置 -
The Android’s location APIs use three different providers to get location -
LocationManager.GPS_PROVIDER
— 此提供程序使用衛(wèi)星確定位置.根據(jù)具體情況,此提供程序可能需要一段時間才能返回定位信息.LocationManager.NETWORK_PROVIDER
— 此提供商根據(jù)蜂窩塔和 WiFi 接入點的可用性確定位置.通過網(wǎng)絡查找來檢索結果.LocationManager.PASSIVE_PROVIDER
— 此提供程序?qū)⒎祷仄渌峁┏绦蛏傻奈恢?當其他應用程序或服務請求位置更新時,您會被動地接收位置更新,而您自己并沒有實際請求位置.
LocationManager.GPS_PROVIDER
— This provider determines location using satellites. Depending on conditions, this provider may take a while to return a location fix.LocationManager.NETWORK_PROVIDER
— This provider determines location based on availability of cell tower and WiFi access points. Results are retrieved by means of a network lookup.LocationManager.PASSIVE_PROVIDER
— This provider will return locations generated by other providers. You passively receive location updates when other applications or services request them without actually requesting the locations yourself.
要點是從系統(tǒng)中獲取LocationManager
的對象,實現(xiàn)LocationListener
,調(diào)用requestLocationUpdates
LocationManager
.
The gist of it is that you get an object of LocationManager
from the system, implement the LocationListener
, and call the requestLocationUpdates
on the LocationManager
.
這是一個代碼片段:
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
makeUseOfNewLocation(location);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
Google 位置策略 API 指南 很好地解釋了代碼.但他們也提到,在大多數(shù)情況下,通過使用 谷歌定位服務 API 代替.現(xiàn)在混亂開始了!
Google’s API Guide on Location Strategies explains the code pretty nicely. But they also mention that in most cases, you’ll get better battery performance, as well as more appropriate accuracy, by using the Google Location Services API instead. Now the confusion starts!
- Google 的定位服務 API
Google 的位置服務 API 是 Google Play 服務 APK 的一部分(方法如下設置它) .它們建立在 Android 的 API 之上.這些 API 提供了一個融合位置提供者",而不是上面提到的提供者.該提供程序會根據(jù)準確性、電池使用情況等自動選擇要使用的底層提供程序.速度很快,因為您可以從不斷更新它的系統(tǒng)范圍的服務中獲取位置.您還可以使用更高級的功能,例如地理圍欄.
Google’s Location Services API is a part of the Google Play Services APK (here’s how to set it up) . They’re built on top of Android’s API. These APIs provide a "Fused Location Provider" instead of the providers mentioned above. This provider automatically chooses what underlying provider to use, based on accuracy, battery usage, etc. It is fast because you get location from a system-wide service that keeps updating it. And you can use more advanced features such as geofencing.
要使用 Google 的定位服務,您的應用需要連接到 GooglePlayServicesClient
.要連接到客戶端,您的活動(或片段等)需要實現(xiàn) GooglePlayServicesClient.ConnectionCallbacks
和 GooglePlayServicesClient.OnConnectionFailedListener
接口.這是一個示例代碼:
To use the Google’s Location Services, your app needs to connect to the GooglePlayServicesClient
. To connect to the client, your activity (or fragment, or so) needs to implement GooglePlayServicesClient.ConnectionCallbacks
and GooglePlayServicesClient.OnConnectionFailedListener
interfaces.
Here’s a sample code:
public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener {
LocationClient locationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
locationClient = new LocationClient(this, this, this);
}
@Override
public void onConnected(Bundle bundle) {
Location location = locationClient.getLastLocation() ;
Toast.makeText(this, "Connected to Google Play Services", Toast.LENGTH_SHORT).show();
}
@Override
public void onDisconnected() {
Toast.makeText(this, "Connected from Google Play Services.", Toast.LENGTH_SHORT).show();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// code to handle failed connection
// this code can be found here — http://developer.android.com/training/location/retrieve-current.html
}
- 為什么
locationClient.getLastLocation()
為空?
locationClient.getLastLocation()
從客戶端獲取最后一個已知位置.但是,F(xiàn)used Location Provider 僅在至少有一個客戶端連接到它時才會維護后臺位置.一旦第一個客戶端連接,它將立即嘗試獲取位置.如果您的活動是第一個連接的客戶端,并且您立即在 onConnected()
中調(diào)用 getLastLocation()
,則可能沒有足夠的時間讓第一個位置進入.這將導致 location
為 null
.
The locationClient.getLastLocation()
gets the last known location from the client. However, the Fused Location Provider will only maintain background location if at least one client is connected to it. Once the first client connects, it will immediately try to get a location. If your activity is the first client to connect and you call getLastLocation()
right away in onConnected()
, that might not be enough time for the first location to come in. This will result in location
being null
.
要解決這個問題,您必須(不確定地)等待,直到提供者獲取位置,然后調(diào)用 getLastLocation()
,這是不可能知道的.另一個(更好的)選擇是實現(xiàn) com.google.android.gms.location.LocationListener
接口以接收定期位置更新(并在獲得第一次更新后將其關閉).
To solve this issue, you have to wait (indeterminately) till the provider gets the location and then call getLastLocation()
, which is impossible to know. Another (better) option is to implement the com.google.android.gms.location.LocationListener
interface to receive periodic location updates (and switch it off once you get the first update).
public class MyActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
// . . . . . . . . more stuff here
LocationRequest locationRequest;
LocationClient locationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
// . . . . other initialization code
locationClient = new LocationClient(this, this, this);
locationRequest = new LocationRequest();
// Use high accuracy
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the update interval to 5 seconds
locationRequest.setInterval(UPDATE_INTERVAL);
// Set the fastest update interval to 1 second
locationRequest.setFastestInterval(FASTEST_INTERVAL);
}
// . . . . . . . . other methods
@Override
public void onConnected(Bundle bundle) {
Location location = locationClient.getLastLocation();
if (location == null)
locationClient.requestLocationUpdates(locationRequest, this);
else
Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
}
// . . . . . . . . other methods
@Override
public void onLocationChanged(Location location) {
locationClient.removeLocationUpdates(this);
// Use the location here!!!
}
在此代碼中,您正在檢查客戶端是否已經(jīng)擁有最后一個位置(在 onConnected
中).如果沒有,您正在請求位置更新,并在收到更新后立即關閉請求(在 onLocationChanged()
回調(diào)中).
In this code, you’re checking if the client already has the last location (in onConnected
). If not, you’re requesting for location updates, and switching off the requests (in onLocationChanged()
callback) as soon as you get an update.
注意 locationClient.requestLocationUpdates(locationRequest, this);
必須在 onConnected
回調(diào)中,否則您將收到 IllegalStateException
因為您將嘗試在未連接到 Google Play 服務客戶端的情況下請求位置.
Note that the locationClient.requestLocationUpdates(locationRequest, this);
has to be inside the onConnected
callback, or else you will get an IllegalStateException
because you will be trying to request for locations without connected to the Google Play Services Client.
- 用戶已禁用定位服務
很多時候,用戶會禁用位置服務(為了節(jié)省電池或隱私原因).在這種情況下,上面的代碼仍然會請求位置更新,但永遠不會調(diào)用 onLocationChanged
.您可以通過檢查用戶是否禁用了定位服務來停止請求.
Many times, the user would have location services disabled (to save battery, or privacy reasons). In such a case, the code above will still request for location updates, but onLocationChanged
will never get called. You can stop the requests by checking if the user has disabled the location services.
如果您的應用要求它們啟用定位服務,您可能需要顯示一條消息或祝酒詞.不幸的是,無法檢查用戶是否在 Google 的位置服務 API 中禁用了位置服務.為此,您將不得不求助于 Android 的 API.
If your app requires them to enable location services, you would want to show a message or a toast. Unfortunately, there is no way of checking if the user has disabled location services in Google’s Location Services API. For this, you will have to resort back to Android’s API.
在您的 onCreate
方法中:
LocationManager manager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
locationEnabled = false;
Toast.makeText(getActivity(), "Enable location services for accurate data", Toast.LENGTH_SHORT).show();
}
else locationEnabled = true;
并在您的 onConnected
方法中使用 locationEnabled
標志,如下所示:
And use the locationEnabled
flag in your onConnected
method like this:
if (location != null) {
Toast.makeText(getActivity(), "Location: " + location.getLatitude() + ", " + location.getLongitude(), Toast.LENGTH_SHORT).show();
}
else if (location == null && locationEnabled) {
locationClient.requestLocationUpdates(locationRequest, this);
}
更新
文檔更新,LocationClient 被移除,api 支持在對話框中一鍵開啟 GPS:
Document is updated, LocationClient is removed and the api supports to enable GPS with one click from dialog:
task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
// All location settings are satisfied. The client can initialize
// location requests here.
// ...
}
});
task.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(MainActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sendEx) {
// Ignore the error.
}
}
}
});
鏈接 https://developer.android.com/training/location/change-location-settings#prompt
新的定位客戶端:FusedLocationProviderClient
New location client: FusedLocationProviderClient
private FusedLocationProviderClient fusedLocationClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}
建議通過https://developer.android.com/training/location 在執(zhí)行任何定位任務之前.
It is recommended to go through https://developer.android.com/training/location before doing any location tasks.
這篇關于Android:LocationManager 與 Google Play 服務的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!