在Android里完美实现基站和WIFI定位
不过其实只要明白了基站/WIFI定位的原理,自己实现基站/WIFI定位其实不难。基站定位一般有几种,第一种是利用手机附近的三个基站进行三角定位,由于每个基站的位置是固定的,利用电磁波在这三个基站间中转所需要时间来算出手机所在的坐标;第二种则是利用获取最近的基站的信息,其中包括基站id,locationareacode、mobilecountrycode、mobilenetworkcode和信号强度,将这些数据发送到google的定位web服务里,就能拿到当前所在的位置信息,误差一般在几十米到几百米之内。其中信号强度这个数据很重要,网上很多所谓的手动通过基站和WIFI信息定位的方法误差大都是因为没使用信号强度而导致误差过大。高德也自己做了一个基站库,具体可以google搜索一下。
现在在一些大中型城市里,WIFI已经普及,有私人或企业的WIFI,亦有中国电信的WIFI,通过WIFI信息进行定位,并不需要真正连接上指定的WIFI路由器,只需要探测到有WIFI存在即可,因此当手机使用的不是GSM制式(因为google的基站库里并没在保存太多的CDMA基站)的时候,也可以使用WIFI进行定位,原理也和基站定位一样,必须要拿到WIFI路由器的SSID和信号强度。
由于有些用户默认是将WIFI关闭的,通过API开启WIFI硬件并进行搜索附近的WIFI路由器需要一段时间,怎样才能将手机基站定位和WIFI定位完美结合起来呢,Android提供了一种很好的机制,就是Handler和Looper,Handler和Looper一般用于跨线程传递数据,但当在单线程里使用时,就变成了一个先进先出的消息泵。利用这个消息泵进行调度,就可以将基站定位和WIFI定位完美结合。以下是相关的代码:
CellInfoManager
importjava.lang.reflect.Method; importjava.util.Iterator; importjava.util.List; importorg.json.JSONArray; importorg.json.JSONException; importorg.json.JSONObject; importandroid.content.Context; importandroid.telephony.CellLocation; importandroid.telephony.NeighboringCellInfo; importandroid.telephony.PhoneStateListener; importandroid.telephony.TelephonyManager; importandroid.telephony.gsm.GsmCellLocation; importandroid.util.Log; publicclassCellInfoManager{ privateintasu; privateintbid; privateintcid; privatebooleanisCdma; privatebooleanisGsm; privateintlac; privateintlat; privatefinalPhoneStateListenerlistener; privateintlng; privateintmcc; privateintmnc; privateintnid; privateintsid; privateTelephonyManagertel; privatebooleanvalid; privateContextcontext; publicCellInfoManager(ContextparamContext){ this.listener=newCellInfoListener(this); tel=(TelephonyManager)paramContext.getSystemService(Context.TELEPHONY_SERVICE); this.tel.listen(this.listener,PhoneStateListener.LISTEN_CELL_LOCATION|PhoneStateListener.LISTEN_SIGNAL_STRENGTH); context=paramContext; } publicstaticintdBm(inti){ intj; if(i>=0&&i<=31) j=i*2+-113; else j=0; returnj; } publicintasu(){ returnthis.asu; } publicintbid(){ if(!this.valid) update(); returnthis.bid; } publicJSONObjectcdmaInfo(){ if(!isCdma()){ returnnull; } JSONObjectjsonObject=newJSONObject(); try{ jsonObject.put("bid",bid()); jsonObject.put("sid",sid()); jsonObject.put("nid",nid()); jsonObject.put("lat",lat()); jsonObject.put("lng",lng()); }catch(JSONExceptionex){ jsonObject=null; Log.e("CellInfoManager",ex.getMessage()); } returnjsonObject; } publicJSONArraycellTowers(){ JSONArrayjsonarray=newJSONArray(); intlat; intmcc; intmnc; intaryCell[]=dumpCells(); lat=lac(); mcc=mcc(); mnc=mnc(); if(aryCell==null||aryCell.length<2){ aryCell=newint[2]; aryCell[0]=cid; aryCell[1]=-60; } for(inti=0;i<aryCell.length;i+=2){ try{ intj2=dBm(i+1); JSONObjectjsonobject=newJSONObject(); jsonobject.put("cell_id",aryCell[i]); jsonobject.put("location_area_code",lat); jsonobject.put("mobile_country_code",mcc); jsonobject.put("mobile_network_code",mnc); jsonobject.put("signal_strength",j2); jsonobject.put("age",0); jsonarray.put(jsonobject); }catch(Exceptionex){ ex.printStackTrace(); Log.e("CellInfoManager",ex.getMessage()); } } if(isCdma()) jsonarray=newJSONArray(); returnjsonarray; } publicintcid(){ if(!this.valid) update(); returnthis.cid; } publicint[]dumpCells(){ int[]aryCells; if(cid()==0){ aryCells=newint[0]; returnaryCells; } List<NeighboringCellInfo>lsCellInfo=this.tel.getNeighboringCellInfo(); if(lsCellInfo==null||lsCellInfo.size()==0){ aryCells=newint[1]; inti=cid(); aryCells[0]=i; returnaryCells; } int[]arrayOfInt1=newint[lsCellInfo.size()*2+2]; intj=0+1; intk=cid(); arrayOfInt1[0]=k; intm=j+1; intn=asu(); arrayOfInt1[j]=n; Iterator<NeighboringCellInfo>iter=lsCellInfo.iterator(); while(true){ if(!iter.hasNext()){ break; } NeighboringCellInfolocalNeighboringCellInfo=(NeighboringCellInfo)iter.next(); inti2=localNeighboringCellInfo.getCid(); if((i2<=0)||(i2==65535)) continue; inti3=m+1; arrayOfInt1[m]=i2; m=i3+1; inti4=localNeighboringCellInfo.getRssi(); arrayOfInt1[i3]=i4; } int[]arrayOfInt2=newint[m]; System.arraycopy(arrayOfInt1,0,arrayOfInt2,0,m); aryCells=arrayOfInt2; returnaryCells; } publicJSONObjectgsmInfo(){ if(!isGsm()){ returnnull; } JSONObjectlocalObject=null; while(true){ try{ JSONObjectlocalJSONObject1=newJSONObject(); Stringstr1=this.tel.getNetworkOperatorName(); localJSONObject1.put("operator",str1); Stringstr2=this.tel.getNetworkOperator(); if((str2.length()==5)||(str2.length()==6)){ Stringstr3=str2.substring(0,3); Stringstr4=str2.substring(3,str2.length()); localJSONObject1.put("mcc",str3); localJSONObject1.put("mnc",str4); } localJSONObject1.put("lac",lac()); int[]arrayOfInt=dumpCells(); JSONArraylocalJSONArray1=newJSONArray(); intk=0; intm=arrayOfInt.length/2; while(true){ if(k>=m){ localJSONObject1.put("cells",localJSONArray1); localObject=localJSONObject1; break; } intn=k*2; inti1=arrayOfInt[n]; inti2=k*2+1; inti3=arrayOfInt[i2]; JSONObjectlocalJSONObject7=newJSONObject(); localJSONObject7.put("cid",i1); localJSONObject7.put("asu",i3); localJSONArray1.put(localJSONObject7); k+=1; } }catch(JSONExceptionlocalJSONException){ localObject=null; } } } publicbooleanisCdma(){ if(!this.valid) update(); returnthis.isCdma; } publicbooleanisGsm(){ if(!this.valid) update(); returnthis.isGsm; } publicintlac(){ if(!this.valid) update(); returnthis.lac; } publicintlat(){ if(!this.valid) update(); returnthis.lat; } publicintlng(){ if(!this.valid) update(); returnthis.lng; } publicintmcc(){ if(!this.valid) update(); returnthis.mcc; } publicintmnc(){ if(!this.valid) update(); returnthis.mnc; } publicintnid(){ if(!this.valid) update(); returnthis.nid; } publicfloatscore(){ floatf1=0f; int[]aryCells=null; inti=0; floatf2=0f; if(isCdma()){ f2=1065353216; returnf2; } if(isGsm()){ f1=0.0F; aryCells=dumpCells(); intj=aryCells.length; if(i>=j) f2=f1; } if(i<=0){ return1065353216; } intm=aryCells[i]; for(i=0;i<m;i++){ if((m<0)||(m>31)) f1+=0.5F; else f1+=1.0F; } f2=f1; returnf2; } publicintsid(){ if(!this.valid) update(); returnthis.sid; } publicvoidupdate(){ this.isGsm=false; this.isCdma=false; this.cid=0; this.lac=0; this.mcc=0; this.mnc=0; CellLocationcellLocation=this.tel.getCellLocation(); intnPhoneType=this.tel.getPhoneType(); if(nPhoneType==1&&cellLocationinstanceofGsmCellLocation){ this.isGsm=true; GsmCellLocationgsmCellLocation=(GsmCellLocation)cellLocation; intnGSMCID=gsmCellLocation.getCid(); if(nGSMCID>0){ if(nGSMCID!=65535){ this.cid=nGSMCID; this.lac=gsmCellLocation.getLac(); } } } try{ StringstrNetworkOperator=this.tel.getNetworkOperator(); intnNetworkOperatorLength=strNetworkOperator.length(); if(nNetworkOperatorLength!=5){ if(nNetworkOperatorLength!=6) ; }else{ this.mcc=Integer.parseInt(strNetworkOperator.substring(0,3)); this.mnc=Integer.parseInt(strNetworkOperator.substring(3,nNetworkOperatorLength)); } if(this.tel.getPhoneType()==2){ this.valid=true; Class<?>clsCellLocation=cellLocation.getClass(); Class<?>[]aryClass=newClass[0]; MethodlocalMethod1=clsCellLocation.getMethod("getBaseStationId",aryClass); MethodlocalMethod2=clsCellLocation.getMethod("getSystemId",aryClass); MethodlocalMethod3=clsCellLocation.getMethod("getNetworkId",aryClass); Object[]aryDummy=newObject[0]; this.bid=((Integer)localMethod1.invoke(cellLocation,aryDummy)).intValue(); this.sid=((Integer)localMethod2.invoke(cellLocation,aryDummy)).intValue(); this.nid=((Integer)localMethod3.invoke(cellLocation,aryDummy)).intValue(); MethodlocalMethod7=clsCellLocation.getMethod("getBaseStationLatitude",aryClass); MethodlocalMethod8=clsCellLocation.getMethod("getBaseStationLongitude",aryClass); this.lat=((Integer)localMethod7.invoke(cellLocation,aryDummy)).intValue(); this.lng=((Integer)localMethod8.invoke(cellLocation,aryDummy)).intValue(); this.isCdma=true; } }catch(Exceptionex){ Log.e("CellInfoManager",ex.getMessage()); } } classCellInfoListenerextendsPhoneStateListener{ CellInfoListener(CellInfoManagermanager){ } publicvoidonCellLocationChanged(CellLocationparamCellLocation){ CellInfoManager.this.valid=false; } publicvoidonSignalStrengthChanged(intparamInt){ CellInfoManager.this.asu=paramInt; } } }
WifiInfoManager
importjava.util.ArrayList; importjava.util.Iterator; importjava.util.List; importorg.json.JSONArray; importorg.json.JSONObject; importandroid.content.Context; importandroid.net.wifi.ScanResult; importandroid.net.wifi.WifiManager; importandroid.util.Log; publicclassWifiInfoManager{ privateWifiManagerwifiManager; publicWifiInfoManager(ContextparamContext){ this.wifiManager=(WifiManager)paramContext.getSystemService(Context.WIFI_SERVICE); } publicList<WifiInfo>dump(){ if(!this.wifiManager.isWifiEnabled()){ returnnewArrayList<WifiInfo>(); } android.net.wifi.WifiInfowifiConnection=this.wifiManager.getConnectionInfo(); WifiInfocurrentWIFI=null; if(wifiConnection!=null){ Strings=wifiConnection.getBSSID(); inti=wifiConnection.getRssi(); Strings1=wifiConnection.getSSID(); currentWIFI=newWifiInfo(s,i,s1); } ArrayList<WifiInfo>lsAllWIFI=newArrayList<WifiInfo>(); if(currentWIFI!=null){ lsAllWIFI.add(currentWIFI); } List<ScanResult>lsScanResult=this.wifiManager.getScanResults(); for(ScanResultresult:lsScanResult){ WifiInfoscanWIFI=newWifiInfo(result); if(!scanWIFI.equals(currentWIFI)) lsAllWIFI.add(scanWIFI); } returnlsAllWIFI; } publicbooleanisWifiEnabled(){ returnthis.wifiManager.isWifiEnabled(); } publicJSONArraywifiInfo(){ JSONArrayjsonArray=newJSONArray(); for(WifiInfowifi:dump()){ JSONObjectlocalJSONObject=wifi.info(); jsonArray.put(localJSONObject); } returnjsonArray; } publicWifiManagerwifiManager(){ returnthis.wifiManager; } publicJSONArraywifiTowers(){ JSONArrayjsonArray=newJSONArray(); try{ Iterator<WifiInfo>localObject=dump().iterator(); while(true){ if(!(localObject).hasNext()){ returnjsonArray; } jsonArray.put(localObject.next().wifi_tower()); } }catch(ExceptionlocalException){ Log.e("location",localException.getMessage()); } returnjsonArray; } publicclassWifiInfoimplementsComparable<WifiInfo>{ publicintcompareTo(WifiInfowifiinfo){ inti=wifiinfo.dBm; intj=dBm; returni-j; } publicbooleanequals(Objectobj){ booleanflag=false; if(obj==this){ flag=true; returnflag; }else{ if(objinstanceofWifiInfo){ WifiInfowifiinfo=(WifiInfo)obj; inti=wifiinfo.dBm; intj=dBm; if(i==j){ Strings=wifiinfo.bssid; Strings1=bssid; if(s.equals(s1)){ flag=true; returnflag; } } flag=false; }else{ flag=false; } } returnflag; } publicinthashCode(){ inti=dBm; intj=bssid.hashCode(); returni^j; } publicJSONObjectinfo(){ JSONObjectjsonobject=newJSONObject(); try{ Strings=bssid; jsonobject.put("mac",s); Strings1=ssid; jsonobject.put("ssid",s1); inti=dBm; jsonobject.put("dbm",i); }catch(Exceptionex){ } returnjsonobject; } publicJSONObjectwifi_tower(){ JSONObjectjsonobject=newJSONObject(); try{ Strings=bssid; jsonobject.put("mac_address",s); inti=dBm; jsonobject.put("signal_strength",i); Strings1=ssid; jsonobject.put("ssid",s1); jsonobject.put("age",0); }catch(Exceptionex){ } returnjsonobject; } publicfinalStringbssid; publicfinalintdBm; publicfinalStringssid; publicWifiInfo(ScanResultscanresult){ Strings=scanresult.BSSID; bssid=s; inti=scanresult.level; dBm=i; Strings1=scanresult.SSID; ssid=s1; } publicWifiInfo(Strings,inti,Strings1){ bssid=s; dBm=i; ssid=s1; } } }
CellLocationManager
importjava.util.ArrayList; importjava.util.Iterator; importjava.util.List; importorg.apache.http.HttpEntity; importorg.apache.http.HttpResponse; importorg.apache.http.client.methods.HttpPost; importorg.apache.http.entity.StringEntity; importorg.apache.http.impl.client.DefaultHttpClient; importorg.apache.http.util.EntityUtils; importorg.json.JSONArray; importorg.json.JSONObject; importandroid.content.BroadcastReceiver; importandroid.content.Context; importandroid.content.Intent; importandroid.content.IntentFilter; importandroid.net.ConnectivityManager; importandroid.net.NetworkInfo; importandroid.net.wifi.WifiManager; importandroid.os.Handler; importandroid.os.Message; importandroid.telephony.CellLocation; importandroid.util.Log; importandroid.widget.Toast; importcom.google.android.photostream.UserTask; publicabstractclassCellLocationManager{ publicstaticintCHECK_INTERVAL=15000; publicstaticbooleanENABLE_WIFI=true; privatestaticbooleanIS_DEBUG=false; privatestaticfinalintSTATE_COLLECTING=2; privatestaticfinalintSTATE_IDLE=0; privatestaticfinalintSTATE_READY=1; privatestaticfinalintSTATE_SENDING=3; privatestaticfinalintMESSAGE_INITIALIZE=1; privatestaticfinalintMESSAGE_COLLECTING_CELL=2; privatestaticfinalintMESSAGE_COLLECTING_WIFI=5; privatestaticfinalintMESSAGE_BEFORE_FINISH=10; privateintaccuracy; privateintbid; privateCellInfoManagercellInfoManager; privateContextcontext; privatebooleandisableWifiAfterScan; privateint[]aryGsmCells; privatedoublelatitude; privatedoublelongitude; privateMyLooperlooper; privatebooleanpaused; privatefinalBroadcastReceiverreceiver; privatelongstartScanTimestamp; privateintstate; privateTasktask; privatelongtimestamp; privatebooleanwaiting4WifiEnable; privateWifiInfoManagerwifiManager; publicCellLocationManager(Contextcontext,CellInfoManagercellinfomanager,WifiInfoManagerwifiinfomanager){ receiver=newCellLocationManagerBroadcastReceiver(); this.context=context.getApplicationContext(); cellInfoManager=cellinfomanager; wifiManager=wifiinfomanager; } privatevoiddebug(ObjectparamObject){ if(IS_DEBUG){ System.out.println(paramObject); Stringstr=String.valueOf(paramObject); Toast.makeText(this.context,str,Toast.LENGTH_SHORT).show(); } } publicintaccuracy(){ returnthis.accuracy; } publicdoublelatitude(){ returnthis.latitude; } publicdoublelongitude(){ returnthis.longitude; } publicabstractvoidonLocationChanged(); publicvoidpause(){ if(state>0&&!paused){ looper.removeMessages(MESSAGE_BEFORE_FINISH); paused=true; } } publicvoidrequestUpdate(){ if(state!=STATE_READY){ return; } booleanbStartScanSuccessful=false; CellLocation.requestLocationUpdate(); state=STATE_COLLECTING; looper.sendEmptyMessage(MESSAGE_INITIALIZE); if(wifiManager.wifiManager().isWifiEnabled()){ bStartScanSuccessful=wifiManager.wifiManager().startScan(); waiting4WifiEnable=false; }else{ startScanTimestamp=System.currentTimeMillis(); if(!ENABLE_WIFI||!wifiManager.wifiManager().setWifiEnabled(true)){ intnDelay=0; if(!bStartScanSuccessful) nDelay=8000; looper.sendEmptyMessageDelayed(MESSAGE_COLLECTING_WIFI,nDelay); debug("CELLUPDATE"); }else{ waiting4WifiEnable=true; } } } publicvoidresume(){ if(state>0&&paused){ paused=false; looper.removeMessages(MESSAGE_BEFORE_FINISH); looper.sendEmptyMessage(MESSAGE_BEFORE_FINISH); } } publicvoidstart(){ if(state<=STATE_IDLE){ Log.i("CellLocationManager","Starting..."); context.registerReceiver(receiver,newIntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); context.registerReceiver(receiver,newIntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)); looper=newMyLooper(); state=STATE_READY; paused=false; waiting4WifiEnable=false; disableWifiAfterScan=false; debug("CELLLOCATIONSTART"); requestUpdate(); } } publicvoidstop(){ if(state>STATE_IDLE){ context.unregisterReceiver(receiver); debug("CELLLOCATIONSTOP"); looper=null; state=STATE_IDLE; if(disableWifiAfterScan){ disableWifiAfterScan=false; wifiManager.wifiManager().setWifiEnabled(false); } } } publiclongtimestamp(){ returnthis.timestamp; } protectedbooleanisConnectedWithInternet(){ ConnectivityManagerconManager=(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfonetworkInfo=conManager.getActiveNetworkInfo(); if(networkInfo!=null){ returnnetworkInfo.isAvailable(); } returnfalse; } privateclassMyLooperextendsHandler{ privatefloatfCellScore; privateJSONArrayobjCellTowersJson; publicvoidhandleMessage(MessageparamMessage){ if(CellLocationManager.this.looper!=this) return; booleanflag=true; switch(paramMessage.what){ default: break; caseMESSAGE_INITIALIZE: this.objCellTowersJson=null; this.fCellScore=1.401298E-045F; caseMESSAGE_COLLECTING_CELL: if(CellLocationManager.this.state!=CellLocationManager.STATE_COLLECTING) break; JSONArrayobjCellTowers=CellLocationManager.this.cellInfoManager.cellTowers(); floatfCellScore=CellLocationManager.this.cellInfoManager.score(); if(objCellTowers!=null){ floatfCurrentCellScore=this.fCellScore; if(fCellScore>fCurrentCellScore){ this.objCellTowersJson=objCellTowers; this.fCellScore=fCellScore; } } this.sendEmptyMessageDelayed(MESSAGE_COLLECTING_CELL,600L); break; caseMESSAGE_COLLECTING_WIFI: if(CellLocationManager.this.state!=CellLocationManager.STATE_COLLECTING) break; this.removeMessages(MESSAGE_COLLECTING_CELL); this.removeMessages(MESSAGE_BEFORE_FINISH); //if(CellLocationManager.this.disableWifiAfterScan&&CellLocationManager.this.wifiManager.wifiManager().setWifiEnabled(true)) //CellLocationManager.this.disableWifiAfterScan=false; CellLocationManager.this.state=CellLocationManager.STATE_SENDING; if(CellLocationManager.this.task!=null) CellLocationManager.this.task.cancel(true); int[]aryCell=null; if(CellLocationManager.this.cellInfoManager.isGsm()) aryCell=CellLocationManager.this.cellInfoManager.dumpCells(); intnBid=CellLocationManager.this.cellInfoManager.bid(); CellLocationManager.this.task=newCellLocationManager.Task(aryCell,nBid); JSONArray[]aryJsonArray=newJSONArray[2]; aryJsonArray[0]=this.objCellTowersJson; aryJsonArray[1]=CellLocationManager.this.wifiManager.wifiTowers(); if(this.objCellTowersJson!=null) Log.i("CellTownerJSON",this.objCellTowersJson.toString()); if(aryJsonArray[1]!=null) Log.i("WIFITownerJSON",aryJsonArray[1].toString()); CellLocationManager.this.debug("Postjson"); CellLocationManager.this.task.execute(aryJsonArray); break; caseMESSAGE_BEFORE_FINISH: if(CellLocationManager.this.state!=CellLocationManager.STATE_READY||CellLocationManager.this.paused) break; //L7 if(CellLocationManager.this.disableWifiAfterScan&&CellLocationManager.this.wifiManager.wifiManager().setWifiEnabled(false)) CellLocationManager.this.disableWifiAfterScan=false; if(!CellLocationManager.this.cellInfoManager.isGsm()){ //L9 if(CellLocationManager.this.bid==CellLocationManager.this.cellInfoManager.bid()){ flag=true; }else{ flag=false; } //L14 if(flag){ requestUpdate(); }else{ this.sendEmptyMessageDelayed(10,CellLocationManager.CHECK_INTERVAL); } }else{ //L8 if(CellLocationManager.this.aryGsmCells==null||CellLocationManager.this.aryGsmCells.length==0){ //L10 flag=true; }else{ int[]aryCells=CellLocationManager.this.cellInfoManager.dumpCells(); if(aryCells!=null&&aryCells.length!=0){ //L13 intnFirstCellId=CellLocationManager.this.aryGsmCells[0]; if(nFirstCellId==aryCells[0]){ //L16 intcellLength=CellLocationManager.this.aryGsmCells.length/2; List<Integer>arraylist=newArrayList<Integer>(cellLength); List<Integer>arraylist1=newArrayList<Integer>(aryCells.length/2); intnIndex=0; intnGSMCellLength=CellLocationManager.this.aryGsmCells.length; while(nIndex<nGSMCellLength){ //gotoL18 arraylist.add(CellLocationManager.this.aryGsmCells[nIndex]); nIndex+=2; } //gotoL17 nIndex=0; while(nIndex<aryCells.length){ //gotoL20 arraylist1.add(aryCells[nIndex]); nIndex+=2; } //gotoL19 intnCounter=0; for(Iterator<Integer>iterator=arraylist.iterator();iterator.hasNext();){ //gotoL22 if(arraylist1.contains(iterator.next())) nCounter++; } //gotoL21 intk4=arraylist.size()-nCounter; intl4=arraylist1.size()-nCounter; if(k4+l4>nCounter) flag=true; else flag=false; if(flag){ StringBuilderstringbuilder=newStringBuilder(k4).append("+"); stringbuilder.append(l4).append(">"); stringbuilder.append(nCounter); CellLocationManager.this.debug(stringbuilder.toString()); } break; }else{ //L15 flag=true; CellLocationManager.this.debug("PRIMARYCELLCHANGED"); //gotoL14 if(flag){ requestUpdate(); }else{ this.sendEmptyMessageDelayed(MESSAGE_BEFORE_FINISH,CellLocationManager.CHECK_INTERVAL); } } }else{ //L12 flag=true; //gotoL14 if(flag){ requestUpdate(); }else{ this.sendEmptyMessageDelayed(MESSAGE_BEFORE_FINISH,CellLocationManager.CHECK_INTERVAL); } } } } } } } classTaskextendsUserTask<JSONArray,Void,Void>{ intaccuracy; intbid; int[]cells; doublelat; doublelng; longtime; publicTask(int[]aryCell,intbid){ this.time=System.currentTimeMillis(); this.cells=aryCell; this.bid=bid; } publicVoiddoInBackground(JSONArray[]paramArrayOfJSONArray){ try{ JSONObjectjsonObject=newJSONObject(); jsonObject.put("version","1.1.0"); jsonObject.put("host","maps.google.com"); jsonObject.put("address_language","zh_CN"); jsonObject.put("request_address",true); jsonObject.put("radio_type","gsm"); jsonObject.put("carrier","HTC"); JSONArraycellJson=paramArrayOfJSONArray[0]; jsonObject.put("cell_towers",cellJson); JSONArraywifiJson=paramArrayOfJSONArray[1]; jsonObject.put("wifi_towers",wifiJson); DefaultHttpClientlocalDefaultHttpClient=newDefaultHttpClient(); HttpPostlocalHttpPost=newHttpPost("http://www.google.com/loc/json"); StringstrJson=jsonObject.toString(); StringEntityobjJsonEntity=newStringEntity(strJson); localHttpPost.setEntity(objJsonEntity); HttpResponseobjResponse=localDefaultHttpClient.execute(localHttpPost); intnStateCode=objResponse.getStatusLine().getStatusCode(); HttpEntityhttpEntity=objResponse.getEntity(); byte[]arrayOfByte=null; if(nStateCode/100==2) arrayOfByte=EntityUtils.toByteArray(httpEntity); httpEntity.consumeContent(); StringstrResponse=newString(arrayOfByte,"UTF-8"); jsonObject=newJSONObject(strResponse); this.lat=jsonObject.getJSONObject("location").getDouble("latitude"); this.lng=jsonObject.getJSONObject("location").getDouble("longitude"); this.accuracy=jsonObject.getJSONObject("location").getInt("accuracy");; }catch(ExceptionlocalException){ returnnull; } returnnull; } publicvoidonPostExecute(VoidparamVoid){ if(CellLocationManager.this.state!=CellLocationManager.STATE_SENDING||CellLocationManager.this.task!=this) return; if((this.lat!=0.0D)&&(this.lng!=0.0D)){ CellLocationManager.this.timestamp=this.time; CellLocationManager.this.latitude=this.lat; CellLocationManager.this.longitude=this.lng; CellLocationManager.this.accuracy=this.accuracy; CellLocationManager.this.aryGsmCells=this.cells; CellLocationManager.this.bid=this.bid; StringBuildersb=newStringBuilder("CELLLOCATIONDONE:("); sb.append(this.lat).append(",").append(this.lng).append(")"); CellLocationManager.this.debug(sb.toString()); CellLocationManager.this.state=STATE_READY; CellLocationManager.this.looper.sendEmptyMessageDelayed(MESSAGE_BEFORE_FINISH,CellLocationManager.CHECK_INTERVAL); CellLocationManager.this.onLocationChanged(); }else{ CellLocationManager.this.task=null; CellLocationManager.this.state=CellLocationManager.STATE_READY; CellLocationManager.this.looper.sendEmptyMessageDelayed(MESSAGE_BEFORE_FINISH,5000L); } } } privateclassCellLocationManagerBroadcastReceiverextendsBroadcastReceiver{ @Override publicvoidonReceive(Contextarg0,Intentintent){ //access$0state //1debug //access$2loop //3startScanTimestamp //4disableWifiAfterScan //5wifimanager if(CellLocationManager.this.state!=CellLocationManager.STATE_COLLECTING) return; Strings=intent.getAction(); if(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(s)){//goto_L4;elsegoto_L3 //_L3: CellLocationManager.this.debug("WIFISCANCOMPLETE"); CellLocationManager.this.looper.removeMessages(MESSAGE_COLLECTING_WIFI); longlInterval=System.currentTimeMillis()-CellLocationManager.this.startScanTimestamp; if(lInterval>4000L) CellLocationManager.this.looper.sendEmptyMessageDelayed(MESSAGE_COLLECTING_WIFI,4000L); else CellLocationManager.this.looper.sendEmptyMessage(MESSAGE_COLLECTING_WIFI); }else{ //_L4: if(!CellLocationManager.this.waiting4WifiEnable) return; Strings1=intent.getAction(); if(!WifiManager.WIFI_STATE_CHANGED_ACTION.equals(s1)) return; intwifiState=intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,4); //_L5: if(wifiState==WifiManager.WIFI_STATE_ENABLING){ booleanflag2=CellLocationManager.this.wifiManager.wifiManager().startScan(); //_L8: CellLocationManager.this.disableWifiAfterScan=true; CellLocationManager.this.paused=false; //inti=flag2?1:0; //intnDelay=i!=0?8000:0; //CellLocationManager.this.looper.sendEmptyMessageDelayed(MESSAGE_COLLECTING_WIFI,nDelay); CellLocationManager.this.debug("WIFIENABLED"); } } } } }
调用方法:
CellInfoManagercellManager=newCellInfoManager(this); WifiInfoManagerwifiManager=newWifiInfoManager(this); CellLocationManagerlocationManager=newCellLocationManager(this,cellManager,wifiManager){ @Override publicvoidonLocationChanged(){ txtAutoNaviInfo.setText(this.latitude()+"-"+this.longitude()); this.stop(); } }; locationManager.start();
如果还想同时使用GPS定位,其实也很简单,可以和FourSquare提供的BestLocationListener结合起来,将上面那段代码添加到BestLocationListener的register方法里:
publicvoidregister(LocationManagerlocationManager,booleangps,Contextcontext){ if(DEBUG)Log.d(TAG,"Registeringthislocationlistener:"+this.toString()); longupdateMinTime=SLOW_LOCATION_UPDATE_MIN_TIME; longupdateMinDistance=SLOW_LOCATION_UPDATE_MIN_DISTANCE; if(gps){ updateMinTime=LOCATION_UPDATE_MIN_TIME; updateMinDistance=LOCATION_UPDATE_MIN_DISTANCE; } List<String>providers=locationManager.getProviders(true); intprovidersCount=providers.size(); if(!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)&&!locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){ setChanged(); notifyObservers(null); } for(inti=0;i<providersCount;i++){ StringproviderName=providers.get(i); if(locationManager.isProviderEnabled(providerName)){ updateLocation(locationManager.getLastKnownLocation(providerName)); } //OnlyregisterwithGPSifwe'veexplicitlyallowedit. if(gps||!LocationManager.GPS_PROVIDER.equals(providerName)){ locationManager.requestLocationUpdates(providerName,updateMinTime, updateMinDistance,this); } } if(cellLocationManager==null){ CellInfoManagercellManager=newCellInfoManager(context); WifiInfoManagerwifiManager=newWifiInfoManager(context); cellLocationManager=newCellLocationManager(context,cellManager,wifiManager){ @Override publicvoidonLocationChanged(){ if((latitude()==0.0D)||(longitude()==0.0D))return; Locationresult=newLocation("CellLocationManager"); result.setLatitude(latitude()); result.setLongitude(longitude()); result.setAccuracy(accuracy()); onBestLocationChanged(result); this.stop(); } }; } //cellLocationManager.stop(); cellLocationManager.start(); //LocationControllercontroller=LocationController.requestLocationUpdates("",updateMinTime,updateMinDistance,this,context); //controller.requestCurrentLocation(); }