在Android开发中地图和定位是很多软件不可或缺的内容,这些特色功能也给人们带来了很多方便。定位一般分为三种方案:即GPS定位、网络定位以及基站定位。
最简单的手机定位方式当然是通过GPS模块定位,GPS方式准确度是最高的,但是它的缺点也非常明显:
1,比较耗电;2,绝大部分用户默认不开启GPS模块;3,从GPS模块启动到获取第一次定位数据,可能需要比较长的时间;4,室内几乎无法使用。这其中,缺点2,3都是比较致命的。需要指出的是,GPS走的是卫星通信的通道,在没有网络连接的情况下也能用。
另外一种常见的定位方式是基站定位。大致思路就是采集到手机上的基站ID号(cellid)和其它的一些信息(MNC,MCC,LAC等等),然后通过网络访问一些定位服务,获取并返回对应的经纬度坐标。基站定位的精确度不如GPS,但好处是能够在室内用,只要网络通畅就行。
还有网络定位。和基站定位类似,这种方式是通过获取当前所用的wifi的一些信息,然后访问网络上的定位服务以获得经纬度坐标。因为它和基站定位其实都需要使用网络,所以在Android中也统称为网络定位。
最后需要解释一点的是AGPS方式。很多人将它和基站定位混为一谈,但其实AGPS的本质仍然是GPS,只是它会使用基站信息对获取GPS进行辅助,然后还能对获取到的GPS结果进行修正,所以AGPS要比传统的GPS更快,准确度略高。
本文将介绍综合使用GPS定位、以及基于网络定位,最后进行地址解析。地址解析主要就是通过获取GPS或网络定位获取经纬度,然后使用经纬度来获取所在的城市及区域。使用地址解析需要使用Internet网络连接,否则会解析失败。网络连接与使用网络定位是两码事,打开网络连接,不开启手机的网络定位设置,也无法使用网络定位。例如我使用的Android手机定位设置如下:
综合定位效果如图:
单独使用网络定位(未使用地址解析):
单独使用GPS定位(未使用地址解析):
详细观察可以发现,GPS定位数据更精细。
接下来分享下代码实现,仅实现简单的定位功能。
1)检查定位设置,至少开启一种定位方法
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (!(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
|| locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))) {
Toast.makeText(this, "请打开网络或GPS定位功能!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(intent, 0);
return;
}
2)获取定位信息,此处我优先使用GPS定位,如果获取失败,再使用网络定位
try {
Location location;
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(location == null){
Log.d(TAG, "onCreate.location = null");
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
Log.d(TAG, "onCreate.location = " + location);
updateView(location);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 5, locationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 5, locationListener);
}catch (SecurityException e){
e.printStackTrace();
}
3)使用获取到的经纬度进行地址解析
private void updateView(Location location) {
Geocoder gc = new Geocoder(this);
List<Address> addresses = null;
String msg = "";
Log.d(TAG, "updateView.location = " + location);
if (location != null) {
try {
addresses = gc.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
Log.d(TAG, "updateView.addresses = " + addresses);
if (addresses.size() > 0) {
msg += addresses.get(0).getAdminArea().substring(0,2);
msg += " " + addresses.get(0).getLocality().substring(0,2);
}
} catch (IOException e) {
e.printStackTrace();
}
editText.setText("定位到的位置:\n");
editText.append(msg);
editText.append("\n经度:");
editText.append(String.valueOf(location.getLongitude()));
editText.append("\n纬度:");
editText.append(String.valueOf(location.getLatitude()));
} else {
editText.getEditableText().clear();
editText.setText("定位中");
}
}
详细代码如下:
package com.example.hornsey.myapplication.Demo;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;
import com.example.hornsey.myapplication.R;
import java.io.IOException;
import java.util.List;
public class GPSDemoActivity extends Activity {
private static final String TAG = "GpsActivity";
private LocationManager locationManager;
private EditText editText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gpsdemo);
editText = (EditText) findViewById(R.id.editText);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (!(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
|| locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER))) {
Toast.makeText(this, "请打开网络或GPS定位功能!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(intent, 0);
return;
}
try {
Location location;
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(location == null){
Log.d(TAG, "onCreate.location = null");
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
Log.d(TAG, "onCreate.location = " + location);
updateView(location);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 5, locationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 5, locationListener);
}catch (SecurityException e){
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
try{
locationManager.removeUpdates(locationListener);
}catch (SecurityException e){
}
super.onDestroy();
}
private LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onProviderDisabled.location = " + location);
updateView(location);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "onStatusChanged() called with " + "provider = [" + provider + "], status = [" + status + "], extras = [" + extras + "]");
switch (status) {
case LocationProvider.AVAILABLE:
Log.i(TAG, "AVAILABLE");
break;
case LocationProvider.OUT_OF_SERVICE:
Log.i(TAG, "OUT_OF_SERVICE");
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
Log.i(TAG, "TEMPORARILY_UNAVAILABLE");
break;
}
}
@Override
public void onProviderEnabled(String provider) {
Log.d(TAG, "onProviderEnabled() called with " + "provider = [" + provider + "]");
try {
Location location = locationManager.getLastKnownLocation(provider);
Log.d(TAG, "onProviderDisabled.location = " + location);
updateView(location);
}catch (SecurityException e){
}
}
@Override
public void onProviderDisabled(String provider) {
Log.d(TAG, "onProviderDisabled() called with " + "provider = [" + provider + "]");
}
};
/**
* 实时更新文本内容
*/
private void updateView(Location location) {
Geocoder gc = new Geocoder(this);
List<Address> addresses = null;
String msg = "";
Log.d(TAG, "updateView.location = " + location);
if (location != null) {
try {
addresses = gc.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
Log.d(TAG, "updateView.addresses = " + addresses);
if (addresses.size() > 0) {
msg += addresses.get(0).getAdminArea().substring(0,2);
msg += " " + addresses.get(0).getLocality().substring(0,2);
}
} catch (IOException e) {
e.printStackTrace();
}
editText.setText("定位到的位置:\n");
editText.append(msg);
editText.append("\n经度:");
editText.append(String.valueOf(location.getLongitude()));
editText.append("\n纬度:");
editText.append(String.valueOf(location.getLatitude()));
} else {
editText.getEditableText().clear();
editText.setText("定位中");
}
}
}
参考文章:
本文介绍了Android开发中GPS定位、网络定位(包括基站和WiFi定位)的原理与应用,并探讨了AGPS辅助定位的优势。通过代码示例展示了如何获取定位信息并进行地址解析,强调了开启定位设置的重要性。
532





