让你的App可定位
用户一般随身携带他们的移动设备,一个独特的特性可用于移动应用程序的是位置识别,当你的应用合理的应用位置服务时,能为你的用户带来更好的移动体验
现在我们来学习怎么把位置服务功能加入到你的应用中,学习不同的方式来获取用户位置的更新和最佳使用位置服务的方法
通过本章你将会学到
使用位置服务管理器
学习在你的应用能使用位置管理服务前必须的一些设置
获取当前的位置
学习如何在我们的平台上使用基础的定位技术获取用户当前的位置
显示位置
学习如何使位置坐标信息变为用户的地址信息
介绍下在Android中的两种定位方式
1、gps定位:内置到手机当中(早期版本的Android手机可能没有此模块),已成为手机的一个模块了,定位比较准确
2、基于网络的定位:这种定位方式需要手机联网,此种方式又分为基于基站定位(WI-FI)和GPRS定位(手机SIM卡),其中基于
基站定位比较准
确,而基于GPRS定位一般不是很准确
Sample中具体实现的步骤
获取位置管理器,判断gps是否可用,如果不可用则引导用户去开启
@Override
protected void onStart() {
super.onStart();
// Check if the GPS setting is currently enabled on the device.
// This verification should be done during onStart() because the system calls this method
// when the user returns to the activity, which ensures the desired location provider is
// enabled each time the activity resumes from the stopped state.
// 获取位置服务管理器
LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
//当前gps是否可用
final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!gpsEnabled) {
// Build an alert dialog here that requests that the user enable
// the location services, then when the user clicks the "OK" button,
// call enableLocationSettings()
// 转到gps设置界面,让用户设置
new EnableGpsDialogFragment().show(getSupportFragmentManager(), "enableGpsDialog");
}
}
获取gps或network定位实例,并注册用户位置移动监听器
// Set up fine and/or coarse location providers depending on whether the fine provider or
// both providers button is pressed.
private void setup() {
Location gpsLocation = null;
Location networkLocation = null;
mLocationManager.removeUpdates(listener);
mLatLng.setText(R.string.unknown);
mAddress.setText(R.string.unknown);
// Get fine location updates only.
if (mUseFine) {
mFineProviderButton.setBackgroundResource(R.drawable.button_active);
mBothProviderButton.setBackgroundResource(R.drawable.button_inactive);
// Request updates from just the fine (gps) provider.
// 获取gps location实例
gpsLocation = requestUpdatesFromProvider(
LocationManager.GPS_PROVIDER, R.string.not_support_gps);
// Update the UI immediately if a location is obtained.
if (gpsLocation != null) updateUILocation(gpsLocation);
} else if (mUseBoth) {
// Get coarse and fine location updates.
mFineProviderButton.setBackgroundResource(R.drawable.button_inactive);
mBothProviderButton.setBackgroundResource(R.drawable.button_active);
// Request updates from both fine (gps) and coarse (network) providers.
gpsLocation = requestUpdatesFromProvider(
LocationManager.GPS_PROVIDER, R.string.not_support_gps);
//获取 network location实例
networkLocation = requestUpdatesFromProvider(
LocationManager.NETWORK_PROVIDER, R.string.not_support_network);
// If both providers return last known locations, compare the two and use the better
// one to update the UI. If only one provider returns a location, use it.
if (gpsLocation != null && networkLocation != null) {
updateUILocation(getBetterLocation(gpsLocation, networkLocation));
} else if (gpsLocation != null) {
updateUILocation(gpsLocation);
} else if (networkLocation != null) {
updateUILocation(networkLocation);
}
}
}
/**
* Method to register location updates with a desired location provider. If the requested
* provider is not available on the device, the app displays a Toast with a message referenced
* by a resource id.
*
* @param provider Name of the requested provider.
* @param errorResId Resource id for the string message to be displayed if the provider does
* not exist on the device.
* @return A previously returned {@link android.location.Location} from the requested provider,
* if exists.
*/
//注册位置改变监听器
private Location requestUpdatesFromProvider(final String provider, final int errorResId) {
Location location = null;
if (mLocationManager.isProviderEnabled(provider)) {
//注册监听器
mLocationManager.requestLocationUpdates(provider, TEN_SECONDS, TEN_METERS, listener);
//最后一次的位置信息会被保存
location = mLocationManager.getLastKnownLocation(provider);
} else {
Toast.makeText(this, errorResId, Toast.LENGTH_LONG).show();
}
return location;
}
//用户位置改变监听器
private final LocationListener listener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
// A new location update is received. Do something useful with it. Update the UI with
// the location update.
//当位置改变时更新用户位置信息
updateUILocation(location);
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
使用AsyncTask来更新UI的方式,增强用户体验
private void doReverseGeocoding(Location location) {
// Since the geocoding API is synchronous and may take a while. You don't want to lock
// up the UI thread. Invoking reverse geocoding in an AsyncTask.
(new ReverseGeocodingTask(this)).execute(new Location[] {location});
}
// AsyncTask encapsulating the reverse-geocoding API. Since the geocoder API is blocked,
// we do not want to invoke it from the UI thread.
private class ReverseGeocodingTask extends AsyncTask<Location, Void, Void> {
Context mContext;
public ReverseGeocodingTask(Context context) {
super();
mContext = context;
}
@Override
protected Void doInBackground(Location... params) {
Geocoder geocoder = new Geocoder(mContext, Locale.getDefault());
Location loc = params[0];
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocation(loc.getLatitude(), loc.getLongitude(), 1);
} catch (IOException e) {
e.printStackTrace();
// Update address field with the exception.
Message.obtain(mHandler, UPDATE_ADDRESS, e.toString()).sendToTarget();
}
if (addresses != null && addresses.size() > 0) {
Address address = addresses.get(0);
// Format the first line of address (if available), city, and country name.
String addressText = String.format("%s, %s, %s",
address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",
address.getLocality(),
address.getCountryName());
// Update address field on UI.
Message.obtain(mHandler, UPDATE_ADDRESS, addressText).sendToTarget();
}
return null;
}
}
当你不再需要定位服务时,注意移除位置改变监听器
// Stop receiving location updates whenever the Activity becomes invisible.
@Override
protected void onStop() {
super.onStop();
mLocationManager.removeUpdates(listener);
}
其实 让你的App来定位比较简单,主要分为
1、获取定位管理服务,选用恰当的定位方式(gps定位最准确,但定位时间比较长,network定位不是很准确尤其是在GPRS网络下,但定位所用
时
间极短)
2、注册用户位置改变监听器,获取用户的当前位置
3、异步更新UI(使用AsyncTask异步类)
最后需要注意的是使用定位服务需要android.permission.ACCESS_FINE_LOCATION权限