手机定位最常用的有两种方式:网络定位、GPS模块定位。前者的优点是速度快,一般几秒内就可以定出位置(网络好的情况),缺点是费流量、精确度相对GPS略低;后者的优点是定位十分精确,可以精确到米,而且不费流量,缺点是速度慢,而且不能有障碍物,比如在室内定位效果就非常差,在空旷的地方可以。<p> 那么,知道这两种地位方式的优缺点之后,该怎么设计程序来较好的完成定位功能呢?首先逻辑非常重要,我的定位策略逻辑如下:</p><p> 1、网络较好时,首选网络定位(因为速度快,现在的手机用户最讨厌那些运行慢的软件了)</p><p> 2、没有网络时,比如去户外远行,选择GPS定位。</p><p> 3、如果网络、GPS都不可用时候,使用内存保留的GPS最近经纬度。(前提是该数据在可用时间范围内)</p><p> 4、如果内存中无GPS位置时,使用内存保留的网络定位经纬度。(前提是该数据在可用时间范围内)</p><p> 5、使用默认经纬度(如果以上都不能得到经纬度,使用默认经纬度,该经纬度是用户最常定位地方的经纬度,可自行设置)</p><p> 6、异常(一般此步不会发生)</p><p> </p><p> 逻辑清楚了,但是代码设计也十分重要,代码质量的健壮性高低决定了程序员最后能走多远。</p><p> 定义一个基类:LocationBase.java(经纬度的属性)</p>
public class LocationBase {
//private long latitude;//经度
//private long longitude;//纬度
LagLng lagLngBean;//经纬度
String lastSavingTime;//上次保存时间
int locationServiceType;//定位类型 1表示GPS,2表示NetWork Wifi,3表示Network 手机网络
/*
public long getLatitude() {
return latitude;
}
public void setLatitude(long latitude) {
this.latitude = latitude;
}
public long getLongitude() {
return longitude;
}
public void setLongitude(long longitude) {
this.longitude = longitude;
}
*/
public String getLastSavingTime() {
return lastSavingTime;
}
public LagLng getLagLngBean() {
return lagLngBean;
}
public void setLagLngBean(LagLng lagLngBean) {
this.lagLngBean = lagLngBean;
}
public void setLastSavingTime(String lastSavingTime) {
this.lastSavingTime = lastSavingTime;
}
public int getLocationServiceType() {
return locationServiceType;
}
public void setLocationServiceType(int locationServiceType) {
this.locationServiceType = locationServiceType;
}
public static String getCurrentDate(){
String currentDate = "";
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss" ,Locale.CHINA);
currentDate = format.format(date);
return currentDate;
}
}
然后定义获取网络定位经纬度和GPS定位的经纬度两个类,他们均是LacationBase的子类。
GPSLocation.java
class GPSLocation extends LocationBase implements LocationListener{
LocationService locationService;
private Context context;
private Location location = null;
boolean gpsFlag = false;
private SharedPreferences sp = null;
public GPSLocation(Context context){
this.context = context;
lagLngBean = new LagLng();
locationService = new LocationService(context);
}
public boolean setCurrentLocation(){
location = locationService.getLocation(LocationManager.GPS_PROVIDER, this);
if(location != null){
lagLngBean.setLatitude(location.getLatitude());
lagLngBean.setLongitude(location.getLongitude());
lastSavingTime = getCurrentDate();
locationServiceType = 1;
StringBuffer buffer = new StringBuffer();
buffer.append(locationServiceType+"#"+lastSavingTime+"#"+location.getLatitude()+"#"+location.getLongitude());
saveCurrentLocation(buffer.toString());
gpsFlag = true;
}else{
gpsFlag = false;
}
return gpsFlag;
}
private void saveCurrentLocation(String locationString){
sp = context.getSharedPreferences("Location", Context.MODE_PRIVATE);
sp.edit().putString("GPSLocation", locationString).commit();
}
@Override
public void onLocationChanged(Location location) {
this.location = location;
System.out.println("GPS定位:==========================="+location);
//位置改变时重新保存
if(location != null){
StringBuffer buffer = new StringBuffer();
buffer.append("1#"+getCurrentDate()+"#"+location.getLatitude()+"#"+location.getLongitude());
saveCurrentLocation(buffer.toString());
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
NetworkLocation.java
/**
* 手机网络定位
* @author Acer
*
*/
class NetworkLocation extends LocationBase implements LocationListener{
LocationService locationService;
private Context context;
private Location location = null;
boolean netFlag = false;
private SharedPreferences sp = null;
public NetworkLocation(Context context){
this.context = context;
locationService = new LocationService(context);
lagLngBean = new LagLng();
}
public boolean setCurrentLocation(){
//判断网络是否可用
if(checkNetWorkState()){
if(location == null)
location = locationService.getLocation(LocationManager.NETWORK_PROVIDER, this);
if(location != null){
lagLngBean.setLatitude(location.getLatitude());
lagLngBean.setLongitude(location.getLongitude());
lastSavingTime = getCurrentDate();
StringBuffer buffer = new StringBuffer();
buffer.append(locationServiceType+"#"+lastSavingTime+"#"+location.getLatitude()+"#"+location.getLongitude());
saveCurrentLocation(buffer.toString());
netFlag = true;
}else{
netFlag = false;
}
}
return netFlag;
}
private void saveCurrentLocation(String locationString){
sp = context.getSharedPreferences("Location", Context.MODE_PRIVATE);
sp.edit().putString("NetWorkLocation", locationString).commit();
}
private boolean checkNetWorkState(){
boolean flag = false;
try {
// 获得手机所有连接管理对象(包括对wi-fi等连接的管理)
ConnectivityManager connectivity = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
// 获得网络连接管理的对象
NetworkInfo info = connectivity.getActiveNetworkInfo();
if (info != null && info.isConnected()) {
// 判断当前网络是否已连接
if (info.getState() == NetworkInfo.State.CONNECTED)
{
if(info.getType() == ConnectivityManager.TYPE_WIFI){
locationServiceType = 2;
}else if(info.getType() == ConnectivityManager.TYPE_MOBILE){
locationServiceType = 3;
}
flag = true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
@Override
public void onLocationChanged(Location location) {
this.location = location;
System.out.println("NetWork定位:==============================="+location);
//位置改变时重新保存
if(location != null && locationServiceType >0){
StringBuffer buffer = new StringBuffer();
buffer.append(locationServiceType+"#"+getCurrentDate()+"#"+location.getLatitude()+"#"+location.getLongitude());
saveCurrentLocation(buffer.toString());
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
}
LocationService.java//选择定位方式
public class LocationService extends Service {
protected LocationManager locationManager;
Location location;
private static final long MIN_DISTANCE_FOR_UPDATE = 10;
private static final long MIN_TIME_FOR_UPDATE = 1000 * 60;
public LocationService(Context context){
locationManager = (LocationManager)context.getSystemService(LOCATION_SERVICE);
}
public Location getLocation(String provider,LocationListener locationListener){
if(locationManager.isProviderEnabled(provider)){
if(provider == LocationManager.GPS_PROVIDER)
locationManager.requestLocationUpdates(provider, MIN_TIME_FOR_UPDATE, MIN_DISTANCE_FOR_UPDATE, locationListener);
else if(provider == LocationManager.NETWORK_PROVIDER)
locationManager.requestLocationUpdates(provider, 0, 0, locationListener);
System.out.println("进入1:"+provider);
}
if(locationManager != null){
location = locationManager.getLastKnownLocation(provider);
if(location != null){
System.out.println("进入2:成功");
return location;
}
}
System.out.println("进入2:失败");
return null;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
获取定位的接口
LocationServiceProvider.java
/**
* 定位信息Provider
* @author Acer
*
*/
public class LocationServiceProvider {
private NetworkLocation networkLocation = null;
private GPSLocation gpsLocation = null;
private Context context;
private LagLng lagLng;
private SharedPreferences sp = null;
public LocationServiceProvider(Context context){
this.context = context;
networkLocation = new NetworkLocation(context);
gpsLocation = new GPSLocation(context);
}
public LagLng getCurrentLocation(){
sp = context.getSharedPreferences("Location", Context.MODE_PRIVATE);
String NetworkLocation = sp.getString("NetWorkLocation", "");
String GPSLocation = sp.getString("GPSLocation", "");
lagLng = new LagLng();
//判断network是否可用
if(networkLocation.setCurrentLocation()){
lagLng.setLocationServiceType(networkLocation.locationServiceType);
lagLng.setLatitude(networkLocation.lagLngBean.getLatitude());
lagLng.setLongitude(networkLocation.lagLngBean.getLongitude());
return lagLng;
}else if(gpsLocation.setCurrentLocation()){//判断GPS是否可用
lagLng.setLocationServiceType(gpsLocation.locationServiceType);
lagLng.setLatitude(gpsLocation.lagLngBean.getLatitude());
lagLng.setLongitude(gpsLocation.lagLngBean.getLongitude());
return lagLng;
}else if(!"".equals(GPSLocation)){//判断存储的GPS位置是否可用
lagLng.setLocationServiceType(Integer.parseInt(GPSLocation.split("#")[0]));
lagLng.setLatitude(Double.parseDouble(GPSLocation.split("#")[2]));
lagLng.setLongitude(Double.parseDouble(GPSLocation.split("#")[3]));
return lagLng;
}else if(!"".equals(NetworkLocation)){//判断存储的network位置是否可用
lagLng.setLocationServiceType(Integer.parseInt(NetworkLocation.split("#")[0]));
lagLng.setLatitude(Double.parseDouble(NetworkLocation.split("#")[2]));
lagLng.setLongitude(Double.parseDouble(NetworkLocation.split("#")[3]));
return lagLng;
}else{//使用默认经纬度
lagLng.setLocationServiceType(0);
lagLng.setLatitude(-36.880595);
lagLng.setLongitude(174.797636);
}
return lagLng;
}
}
最后在主函数中调用就很简单了:
lsp = new LocationServiceProvider(this);
lagLng = lsp.getCurrentLocation();//即可获得经纬度
MainActivity.java主函数调用
public class MainActivity extends Activity {
private TextView tvLocation,tvLocationMethod,tvLocationState;
private int locationType;
private double latitude = 0;
private double longitude = 0;
private String method = "默认";
private String state = "搜索中";
private LocationServiceProvider lsp = null;
private LagLng lagLng = null;
private ProgressDialog pd = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvLocation = (TextView)findViewById(R.id.location);
tvLocationMethod = (TextView)findViewById(R.id.location_method);
tvLocationState = (TextView)findViewById(R.id.location_state);
pd = new ProgressDialog(this);
pd.setMessage("搜索中");
pd.setCancelable(true);
lsp = new LocationServiceProvider(this);
}
@Override
protected void onResume() {
super.onResume();
if(checkNetWorkState()){
pd.show();
getLocation();
}else{
showSettingNetwork(this);
getLocation();
}
}
private void updateUI() {
tvLocation.setText("经纬度("+latitude+","+longitude+")");
tvLocationMethod.setText("定位方式("+method+")");
tvLocationState.setText("定位状态("+state+")");
}
private void getLocation(){
lagLng = lsp.getCurrentLocation();
locationType = lagLng.getLocationServiceType();
state = "待机中";
latitude = lagLng.getLatitude();
longitude = lagLng.getLongitude();
switch (locationType) {
case 1:
method = "GPS";
break;
case 2:
method = "WIFI";
break;
case 3:
method = "手机网络";
break;
default:
method = "默认";
break;
}
updateUI();
pd.dismiss();
}
private boolean checkNetWorkState(){
boolean flag = false;
try {
// 获得手机所有连接管理对象(包括对wi-fi等连接的管理)
ConnectivityManager connectivity = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
// 获得网络连接管理的对象
NetworkInfo info = connectivity.getActiveNetworkInfo();
if (info != null && info.isConnected()) {
// 判断当前网络是否已连接
if (info.getState() == NetworkInfo.State.CONNECTED)
{
flag = true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
public void showSettingNetwork(final Context context){
new AlertDialog.Builder(context)
.setTitle("提示")
.setMessage("亲,你还没有设置网络哦,网络定位速度更快,要马上去设置吗?")
.setPositiveButton("是的", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
}
})
.setNegativeButton("不,待会儿", null)
.create().show();
}
}