第一次来写,记录下android开发过程中的心得体会,也不知从何写起。
笔者就浅谈一下android Location,大家都知道android Location 分为两大类:原生定位、第三方定位(百度地图等)。
而原生定位又细分为两小类:GPS定位、网络定位;
通过GPS定位,较精确,也比较耗电,而网络定位精度不高,省电。为了保证精确度,优先考虑GPS定位。
笔者今天写了一个小demo,从代码的角度,来了解一下原生定位。
首先创建一个Android 工程 Location。
第二步写布局文件xml,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.demo.location.MainActivity">
<TextView
android:id="@+id/tv_longitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_centerHorizontal="true"
android:text="longitude:" />
<TextView
android:id="@+id/tv_latitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="latitude:"
android:textSize="20sp"
android:layout_centerHorizontal="true"
android:layout_below="@+id/tv_longitude"/>
<TextView
android:id="@+id/tv_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="地址"
android:layout_centerHorizontal="true"
android:textSize="20sp"
android:layout_below="@+id/tv_latitude"/>
</RelativeLayout>
第三步增加权限,修改AndroidManifest.xml 代码如下:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
第四步写定位工具类LocationUtils,代码如下图所示:
package com.demo.location;
import android.content.Context;
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 java.io.IOException;
import java.util.List;
import java.util.Locale;
/**
* @className: LocationUtils
* @classDescription: 定位工具类
* @author: leibing
* @createTime: 2016/5/12
*/
public class LocationUtils {
// GPS定位
private final static String GPS_LOCATION = LocationManager.GPS_PROVIDER;
// 网络定位
private final static String NETWORK_LOCATION = LocationManager.NETWORK_PROVIDER;
// 解码经纬度最大结果数目
private final static int MAX_RESULTS = 1;
// 时间更新间隔,单位:ms
private final static long MIN_TIME = 1000;
// 位置刷新距离,单位:m
private final static float MIN_DISTANCE = (float) 0.01;
// singleton
private static LocationUtils instance;
// 定位回调
private LocationCallBack mLocationCallBack;
// 定位管理实例
LocationManager mLocationManager;
// 上下文
private Context mContext;
/**
* 构造函数
* @author leibing
* @createTime 2016/5/12
* @lastModify 2016/5/12
* @param mContext 上下文
* @return
*/
private LocationUtils(Context mContext) {
this.mContext = mContext;
}
/**
* singleton
* @author leibing
* @createTime 2016/5/12
* @lastModify 2016/5/12
* @param mContext 上下文
* @return
*/
public static LocationUtils getInstance(Context mContext) {
if (instance == null) {
instance = new LocationUtils(mContext);
}
return instance;
}
/**
* 获取定位
* @author leibing
* @createTime 2016/5/12
* @lastModify 2016/5/12
* @param mLocationCallBack 定位回调
* @return
*/
@SuppressWarnings("MissingPermission")
public void getLocation(LocationCallBack mLocationCallBack) {
this.mLocationCallBack = mLocationCallBack;
if (mLocationCallBack == null)
return;
// 定位管理初始化
mLocationManager = (LocationManager)
mContext.getSystemService(Context.LOCATION_SERVICE);
// 通过GPS定位,较精确,也比较耗电
LocationProvider gpsProvider =
mLocationManager.getProvider(LocationManager.GPS_PROVIDER);
// 通过网络定位,对定位精度度不高或省点情况可考虑使用
LocationProvider netProvider =
mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER);
// 优先考虑GPS定位,其次网络定位。
if (gpsProvider != null){
gpsLocation();
}else if(netProvider != null){
netWorkLocation();
}else {
mLocationCallBack.setLocation(null);
}
}
/**
* GPS定位
* @author leibing
* @createTime 2016/5/12
* @lastModify 2016/5/12
* @return
*/
@SuppressWarnings("MissingPermission")
private void gpsLocation(){
if (mLocationManager == null)
mLocationManager = (LocationManager)
mContext.getSystemService(Context.LOCATION_SERVICE);
mLocationManager.requestLocationUpdates(
GPS_LOCATION, MIN_TIME, MIN_DISTANCE,mLocationListener);
}
/**
* 网络定位
* @author leibing
* @createTime 2016/5/12
* @lastModify 2016/5/12
* @return
*/
@SuppressWarnings("MissingPermission")
private void netWorkLocation(){
if (mLocationManager == null)
mLocationManager = (LocationManager)
mContext.getSystemService(Context.LOCATION_SERVICE);
mLocationManager.requestLocationUpdates(
NETWORK_LOCATION, MIN_TIME, MIN_DISTANCE,mLocationListener);
}
// 定位监听
private LocationListener mLocationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
if (mLocationCallBack != null){
mLocationCallBack.setLocation(location);
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
// 如果gps定位不可用,改用网络定位
if (provider.equals(LocationManager.GPS_PROVIDER)){
netWorkLocation();
}
}
};
/**
* 根据经纬度获取地址
* @author leibing
* @createTime 2016/5/12
* @lastModify 2016/5/12
* @param latitude 纬度
* @param longitude 经度
* @return
*/
public void getAddress(double latitude, double longitude){
// Address列表
List<Address> locationList = null;
// 经纬度解码实例
Geocoder gc = new Geocoder(mContext, Locale.getDefault());
try {
// 获取Address列表
locationList = gc.getFromLocation(latitude, longitude, MAX_RESULTS);
// 获取Address实例
Address address = locationList.get(0);
if (mLocationCallBack != null)
mLocationCallBack.setAddress(address);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取地址周边信息
* @author leibing
* @createTime 2016/5/12
* @lastModify 2016/5/12
* @param
* @return
*/
public String getAddressLine(Address address){
String result = "";
for (int i = 0; address.getAddressLine(i) != null; i++) {
String addressLine = address.getAddressLine(i);
result = result + addressLine;
}
return result;
}
/**
* @className: LocationCallBack
* @classDescription: 定位回调
* @author: leibing
* @createTime: 2016/5/12
*/
public interface LocationCallBack{
void setLocation(Location location);
void setAddress(Address address);
}
}
看上面代码可知,使用LocationProvider方法设置Location定位方法并在onLocationChanged监听方法中拿到Location,有同学会问,如果不移动是不是拿不到Location,定位经纬度会飘还有就是在mLocationManager.requestLocationUpdates方法中可以设置位置刷新距离参数,把这个距离参数设置足够小,就能实时地拿到当前经纬度坐标。
从定位工具类中可知,优先是考虑GPS定位的,如果GPS定位 disabled,改用网络定位。
第五步写Demo Activity类,代码如下:
package com.demo.location;
import android.location.Address;
import android.location.Location;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
/**
* 经度显示控件
*/
private TextView longitudeTv;
/**
* 纬度显示控件
*/
private TextView latitudeTv;
/**
* 地址显示控件
*/
private TextView addressTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// FindViewById
longitudeTv = (TextView) findViewById(R.id.tv_longitude);
latitudeTv = (TextView) findViewById(R.id.tv_latitude);
addressTv = (TextView) findViewById(R.id.tv_address);
// 获取定位信息
LocationUtils.getInstance(this).getLocation(new LocationUtils.LocationCallBack() {
@Override
public void setLocation(Location location) {
if (location != null){
longitudeTv.setText("经度:" + String.valueOf(location.getLongitude()));
latitudeTv.setText("纬度:" + String.valueOf(location.getLatitude()));
LocationUtils.getInstance(MainActivity.this).getAddress(location.getLatitude(),
location.getLongitude());
}
}
@Override
public void setAddress(Address address) {
if (address != null){
addressTv.setText(
"国家:" + address.getCountryName() + "\n"
+ "城市名:" + address.getLocality() + "\n"
+ "周边信息:" + LocationUtils.getInstance(MainActivity.this).
getAddressLine(address));
}
}
});
}
}
第六步 运行Location Demo,运行结果如下: