Android結(jié)合WiFi、GPS和基站的定位,定義的定位流程為WiFi-->>GPS-->>基站,精確度來說,
WiFi是最高的,不過WiFi定位需要依賴于周邊環(huán)境,附近的WiFi越多,定位就越準(zhǔn)確,在一些鄉(xiāng)鎮(zhèn)城市的話,WiFi定位可能就沒有那么精確。
GPS定位在室內(nèi)的話,基本是無法獲取到定位信息的,不過在室外空曠一點(diǎn)的地方,GPS定位還是比較精確的。
基站定位的話,不多說,精確度偏差是最大的了。
1.WiFi定位
WiFi定位的原理大致是,因?yàn)槊恳粋€(gè)無線AP都有一個(gè)全球唯一的MAC地址,就是獲取到WiFi的MAC地址然后去后臺(tái)數(shù)據(jù)庫(kù)去匹配(這個(gè)需要后臺(tái)數(shù)據(jù)庫(kù)足夠強(qiáng)大,越強(qiáng)大匹配的越準(zhǔn))。這邊提供一個(gè)WiFi地址查詢的地址:點(diǎn)擊我(如侵刪)
1.1掃描手機(jī)當(dāng)前連接的WiFi(WiFi開啟關(guān)閉狀態(tài),以下就直接忽略不寫,具體使用的時(shí)候需要注意)
<!--WiFi狀態(tài)讀取權(quán)限-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
//獲取當(dāng)前連接的WiFi
WifiInfo info = wifiManager .getConnectionInfo();
1.2得到當(dāng)前WiFi對(duì)象信息,BSSID對(duì)應(yīng)為Mac地址

WiFi對(duì)象信息
WiFi定位的原則是最好能獲取到附近的幾個(gè)WiFi熱點(diǎn),然后將幾個(gè)WiFi進(jìn)行位置的糾偏。
2.GPS定位
<!-- GPS權(quán)限 -->
<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" />
需要打開手機(jī)GPS的位置信息模式為:高精度,這一步很重要,會(huì)一直都無法獲取到定位信息

模式:高精度
開始定位
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定位失敗
}
/**
* 開始請(qǐng)求gps定位
*
* @param locationProvider 參數(shù)1,設(shè)備:有GPS_PROVIDER和NETWORK_PROVIDER兩種,前者是GPS,后者是GPRS以及WIFI定位
* @param minTime 位置信息更新周期.單位是毫秒
* @param minDistance 位置變化最小距離:當(dāng)位置距離變化超過此值時(shí),將更新位置信息
* 備注:參數(shù)2和3,如果參數(shù)3不為0,則以參數(shù)3為準(zhǔn);參數(shù)3為0,則通過時(shí)間來定時(shí)更新;兩者為0,則隨時(shí)刷新
*/
private void startRequestLocationUpdates(String locationProvider, long minTime, float minDistance) {
locationManager.requestLocationUpdates(locationProvider, minTime, minDistance, locationListener);
}
//監(jiān)聽回調(diào)
LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
//位置信息變化時(shí)觸發(fā),一旦觸發(fā)這個(gè)回調(diào)就證明GPS定位成功,這個(gè)方法是一直都會(huì)回調(diào)的,在一定的時(shí)間內(nèi),需要設(shè)置一個(gè)超時(shí),以免耗電。
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
switch (status) {
case LocationProvider.AVAILABLE:
//當(dāng)前GPS狀態(tài)為可見狀態(tài)
break;
case LocationProvider.OUT_OF_SERVICE:
//當(dāng)前GPS狀態(tài)為服務(wù)區(qū)外狀態(tài)
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
//當(dāng)前GPS狀態(tài)為暫停服務(wù)狀態(tài)
break;
default:
break;
}
}
@Override
public void onProviderEnabled(String provider) {
//GPS開啟時(shí)觸發(fā)
}
@Override
public void onProviderDisabled(String provider) {
//GPS禁用時(shí)觸發(fā)
}
}
一旦觸發(fā)onLocationChanged方法就可以得到GPS返回的經(jīng)緯度,你就可以通過這個(gè)經(jīng)緯去取查詢位置啦。點(diǎn)擊查詢GPS定位(如侵刪)
關(guān)閉GPS定位
if (locationManager != null) {
locationManager.removeUpdates(locationListener);
locationManager = null;
}
if (locationListener != null) {
locationListener = null;
}
3.基站定位
基站的一些參數(shù)說明:
MCC,Mobile Country Code,移動(dòng)國(guó)家代碼(中國(guó)的為460);
MNC,Mobile Network Code,移動(dòng)網(wǎng)絡(luò)號(hào)碼(中國(guó)移動(dòng)為0,中國(guó)聯(lián)通為1,中國(guó)電信為2);
LAC,Location Area Code,位置區(qū)域碼;
CID,Cell Identity,基站編號(hào);
BSSS,Base station signal strength,基站信號(hào)強(qiáng)度。
1.1獲取當(dāng)前手機(jī)連接的基站信息
TelephonyManager mTelephonyManager = (TelephonyManager) mContext.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephonyManager == null) {
return;
}
String operator = mTelephonyManager.getNetworkOperator();
//獲取的基站信息是
if (operator == null || operator.length() < 5) {
//獲取基站信息有問題,可能是手機(jī)沒插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) {
//可能是手機(jī)沒插sim卡之類的,返回獲取基站失敗
return;
}
//因?yàn)橐苿?dòng)聯(lián)通電信基站的不同,所以需要區(qū)分基站類型
//中國(guó)移動(dòng)和中國(guó)聯(lián)通獲取LAC,CID的方式
if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
//當(dāng)前連接的是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);
}
//中國(guó)電信獲取LAC,CID的方式
if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
//當(dāng)前連接是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獲取獲取附近的基站信息
// 獲取鄰區(qū)基站信息
List<CellInfo> infos = mTelephonyManager.getAllCellInfo();
if(infos==null){
//沒有獲取附近任何的基站信息
return;
}
基站類型的話,也是分為好幾種類型的,需要做區(qū)分的處理
for (CellInfo i : infos) {
if (i instanceof CellInfoGsm) {//gsm基站
Log.i(TAG, "附近發(fā)現(xiàn)gsm基站Mcc = " + cellIdentityGsm.getMcc());
Log.i(TAG, "附近發(fā)現(xiàn)gsm基站Mnc = " + cellIdentityGsm.getMnc());
Log.i(TAG, "附近發(fā)現(xiàn)gsm基站Lac = " + cellIdentityGsm.getLac());
Log.i(TAG, "附近發(fā)現(xiàn)gsm基站Cid = " + cellIdentityGsm.getCid());
}else if (i instanceof CellInfoCdma) {//cdma基站
Log.i(TAG, "附近發(fā)現(xiàn)cdma基站sid = " + cellIdentityCdma.getSystemId());
Log.i(TAG, "附近發(fā)現(xiàn)cdma基站nid = " + cellIdentityCdma.getNetworkId());
Log.i(TAG, "附近發(fā)現(xiàn)cdma基站sid = " + cellIdentityCdma.getBasestationId());
}else if (i instanceof CellInfoLte) {//lte基站
Log.i(TAG, "附近發(fā)現(xiàn)lte基站Mcc = " + cellIdentityLte.getMcc());
Log.i(TAG, "附近發(fā)現(xiàn)lte基站Mnc = " + cellIdentityLte.getMnc());
Log.i(TAG, "附近發(fā)現(xiàn)lte基站Lac = " + cellIdentityLte.getTac());
Log.i(TAG, "附近發(fā)現(xiàn)lte基站Cid = " + cellIdentityLte.getCi());
}else if (i instanceof CellInfoWcdma) {//wcdma基站
Log.i(TAG, "附近發(fā)現(xiàn)wcdma基站Mcc = " + cellIdentityWcdma.getMcc());
Log.i(TAG, "附近發(fā)現(xiàn)wcdma基站Mnc = " + cellIdentityWcdma.getMnc());
Log.i(TAG, "附近發(fā)現(xiàn)wcdma基站Lac = " + cellIdentityWcdma.getLac());
Log.i(TAG, "附近發(fā)現(xiàn)wcdma基站Cid = " + cellIdentityWcdma.getCid());
}
}