Android结合WiFi、GPS和基站的定位,定义的定位流程为WiFi-->>GPS-->>基站,精确度来说,
WiFi是最高的,不过WiFi定位需要依赖于周边环境,附近的WiFi越多,定位就越准确,在一些乡镇城市的话,WiFi定位可能就没有那么精确。
GPS定位在室内的话,基本是无法获取到定位信息的,不过在室外空旷一点的地方,GPS定位还是比较精确的。
基站定位的话,不多说,精确度偏差是最大的了。
1.WiFi定位
WiFi定位的原理大致是,因为每一个无线AP都有一个全球唯一的MAC地址,就是获取到WiFi的MAC地址然后去后台数据库去匹配(这个需要后台数据库足够强大,越强大匹配的越准)。这边提供一个WiFi地址查询的地址:点击我(如侵删)
1.1扫描手机当前连接的WiFi(WiFi开启关闭状态,以下就直接忽略不写,具体使用的时候需要注意)
<!--WiFi状态读取权限-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
//获取当前连接的WiFi
WifiInfo info = wifiManager .getConnectionInfo();
1.2得到当前WiFi对象信息,BSSID对应为Mac地址
WiFi对象信息WiFi定位的原则是最好能获取到附近的几个WiFi热点,然后将几个WiFi进行位置的纠偏。
2.GPS定位
<!-- GPS权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
需要打开手机GPS的位置信息模式为:高精度,这一步很重要,会一直都无法获取到定位信息
模式:高精度开始定位
LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
//获取所有可用的位置提供器
List<String> providers = locationManager.getProviders(true);
if (providers.contains(LocationManager.GPS_PROVIDER)) {
//GPS定位
locationProvider = LocationManager.GPS_PROVIDER;
startRequestLocationUpdates(locationProvider, 0, 0);
} else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
// Network定位
locationProvider = LocationManager.NETWORK_PROVIDER;
if (locationManager.getAllProviders().contains(LocationManager.NETWORK_PROVIDER) &&
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
startRequestLocationUpdates(locationProvider, 0, 0);
}
} else {
//没有可用的位置提供器,GPS定位失败
}
/**
* 开始请求gps定位
*
* @param locationProvider 参数1,设备:有GPS_PROVIDER和NETWORK_PROVIDER两种,前者是GPS,后者是GPRS以及WIFI定位
* @param minTime 位置信息更新周期.单位是毫秒
* @param minDistance 位置变化最小距离:当位置距离变化超过此值时,将更新位置信息
* 备注:参数2和3,如果参数3不为0,则以参数3为准;参数3为0,则通过时间来定时更新;两者为0,则随时刷新
*/
private void startRequestLocationUpdates(String locationProvider, long minTime, float minDistance) {
locationManager.requestLocationUpdates(locationProvider, minTime, minDistance, locationListener);
}
//监听回调
LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
//位置信息变化时触发,一旦触发这个回调就证明GPS定位成功,这个方法是一直都会回调的,在一定的时间内,需要设置一个超时,以免耗电。
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
switch (status) {
case LocationProvider.AVAILABLE:
//当前GPS状态为可见状态
break;
case LocationProvider.OUT_OF_SERVICE:
//当前GPS状态为服务区外状态
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
//当前GPS状态为暂停服务状态
break;
default:
break;
}
}
@Override
public void onProviderEnabled(String provider) {
//GPS开启时触发
}
@Override
public void onProviderDisabled(String provider) {
//GPS禁用时触发
}
}
一旦触发onLocationChanged方法就可以得到GPS返回的经纬度,你就可以通过这个经纬去取查询位置啦。点击查询GPS定位(如侵删)
关闭GPS定位
if (locationManager != null) {
locationManager.removeUpdates(locationListener);
locationManager = null;
}
if (locationListener != null) {
locationListener = null;
}
3.基站定位
基站的一些参数说明:
MCC,Mobile Country Code,移动国家代码(中国的为460);
MNC,Mobile Network Code,移动网络号码(中国移动为0,中国联通为1,中国电信为2);
LAC,Location Area Code,位置区域码;
CID,Cell Identity,基站编号;
BSSS,Base station signal strength,基站信号强度。
1.1获取当前手机连接的基站信息
TelephonyManager mTelephonyManager = (TelephonyManager) mContext.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephonyManager == null) {
return;
}
String operator = mTelephonyManager.getNetworkOperator();
//获取的基站信息是
if (operator == null || operator.length() < 5) {
//获取基站信息有问题,可能是手机没插sim卡
return;
}
int mcc = Integer.parseInt(operator.substring(0, 3));
int mnc = Integer.parseInt(operator.substring(3));
int lac;
int cellId;
CellLocation cellLocation = mTelephonyManager.getCellLocation();
if (cellLocation == null) {
//可能是手机没插sim卡之类的,返回获取基站失败
return;
}
//因为移动联通电信基站的不同,所以需要区分基站类型
//中国移动和中国联通获取LAC,CID的方式
if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
//当前连接的是gsm基站
GsmCellLocation location = (GsmCellLocation) cellLocation;
lac = location.getLac();
cellId = location.getCid();
BaseStationInfo baseStationInfo = new BaseStationInfo();
baseStationInfo.setMcc(mcc);
baseStationInfo.setMnc(mnc);
baseStationInfo.setLac(lac);
baseStationInfo.setCid(cellId);
baseStationInfo.setBaseType(0);
}
//中国电信获取LAC,CID的方式
if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
//当前连接是cdma基站
CdmaCellLocation cdma = (CdmaCellLocation) mTelephonyManager.getCellLocation();
BaseStationInfo baseStationInfo = new BaseStationInfo();
baseStationInfo.setBaseType(1);
baseStationInfo.setSid(cdma.getSystemId());
baseStationInfo.setNid(cdma.getNetworkId());
baseStationInfo.setBid(cdma.getBaseStationId());
}
1.2获取获取附近的基站信息
// 获取邻区基站信息
List<CellInfo> infos = mTelephonyManager.getAllCellInfo();
if(infos==null){
//没有获取附近任何的基站信息
return;
}
基站类型的话,也是分为好几种类型的,需要做区分的处理
for (CellInfo i : infos) {
if (i instanceof CellInfoGsm) {//gsm基站
Log.i(TAG, "附近发现gsm基站Mcc = " + cellIdentityGsm.getMcc());
Log.i(TAG, "附近发现gsm基站Mnc = " + cellIdentityGsm.getMnc());
Log.i(TAG, "附近发现gsm基站Lac = " + cellIdentityGsm.getLac());
Log.i(TAG, "附近发现gsm基站Cid = " + cellIdentityGsm.getCid());
}else if (i instanceof CellInfoCdma) {//cdma基站
Log.i(TAG, "附近发现cdma基站sid = " + cellIdentityCdma.getSystemId());
Log.i(TAG, "附近发现cdma基站nid = " + cellIdentityCdma.getNetworkId());
Log.i(TAG, "附近发现cdma基站sid = " + cellIdentityCdma.getBasestationId());
}else if (i instanceof CellInfoLte) {//lte基站
Log.i(TAG, "附近发现lte基站Mcc = " + cellIdentityLte.getMcc());
Log.i(TAG, "附近发现lte基站Mnc = " + cellIdentityLte.getMnc());
Log.i(TAG, "附近发现lte基站Lac = " + cellIdentityLte.getTac());
Log.i(TAG, "附近发现lte基站Cid = " + cellIdentityLte.getCi());
}else if (i instanceof CellInfoWcdma) {//wcdma基站
Log.i(TAG, "附近发现wcdma基站Mcc = " + cellIdentityWcdma.getMcc());
Log.i(TAG, "附近发现wcdma基站Mnc = " + cellIdentityWcdma.getMnc());
Log.i(TAG, "附近发现wcdma基站Lac = " + cellIdentityWcdma.getLac());
Log.i(TAG, "附近发现wcdma基站Cid = " + cellIdentityWcdma.getCid());
}
}
网友评论