转自:http://fengzhizi715.iteye.com/blog/825716

android可以借助于gps实现定位,但是很多地方是使用gps无法定位比如在室内,而且gps定位的话速度慢。

那么如何克服这样的缺点使得应用程序在室内也可以定位呢?办法是有的借助于基站和wifi进行定位。具体的细节可参考:
http://code.google.com/intl/zh-CN/apis/gears/geolocation_network_protocol.html


下面的代码实现了定位的大致功能
CellIDInfo.java 封装了cellid的信息

public class CellIDInfo { public int cellId; public String mobileCountryCode; public String mobileNetworkCode; public int locationAreaCode; public String radioType; public CellIDInfo(){} }

WifiInfo.java 封装了wifi的信息

public class WifiInfo { public String mac; public WifiInfo(){} }

CellIDInfoManager.java 可获取所有的CellIDInfo

import java.util.ArrayList; import java.util.List; import android.content.Context; import android.telephony.NeighboringCellInfo; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.telephony.cdma.CdmaCellLocation; import android.telephony.gsm.GsmCellLocation; public class CellIDInfoManager { private TelephonyManager manager; private PhoneStateListener listener; private GsmCellLocation gsm; private CdmaCellLocation cdma; int lac; String current_ci,mcc, mnc; public CellIDInfoManager(){} public ArrayList<CellIDInfo> getCellIDInfo(Context context){ manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); listener = new PhoneStateListener(); manager.listen(listener, 0); ArrayList<CellIDInfo> CellID = new ArrayList<CellIDInfo>(); CellIDInfo currentCell = new CellIDInfo(); int type = manager.getNetworkType(); if (type == TelephonyManager.NETWORK_TYPE_GPRS || type ==TelephonyManager.NETWORK_TYPE_EDGE || type ==TelephonyManager.NETWORK_TYPE_HSDPA) { gsm = ((GsmCellLocation) manager.getCellLocation()); if (gsm == null) return null; lac = gsm.getLac(); mcc = manager.getNetworkOperator().substring(0, 3); mnc = manager.getNetworkOperator().substring(3, 5); currentCell.cellId = gsm.getCid(); currentCell.mobileCountryCode = mcc; currentCell.mobileNetworkCode = mnc; currentCell.locationAreaCode = lac; currentCell.radioType = "gsm"; CellID.add(currentCell); List<NeighboringCellInfo> list = manager.getNeighboringCellInfo(); int size = list.size(); for (int i = 0; i < size; i++) { CellIDInfo info = new CellIDInfo(); info.cellId = list.get(i).getCid(); info.mobileCountryCode = mcc; info.mobileCountryCode = mnc; info.locationAreaCode = lac; CellID.add(info); } return CellID; } else if (type == TelephonyManager.NETWORK_TYPE_CDMA || type ==TelephonyManager.NETWORK_TYPE_1xRTT) { cdma = ((CdmaCellLocation) manager.getCellLocation()); if (cdma == null) return null; if ("460".equals(manager.getSimOperator().substring(0, 3))) return null; } return null; } }

WifiInfoManager.java 可获取wifi的信息,目前我只取了当前连接的wifi,没有获取所有能扫描到的wifi信息。

import java.util.ArrayList; import android.content.Context; import android.net.wifi.WifiManager; public class WifiInfoManager { WifiManager wm; public WifiInfoManager(){} public ArrayList getWifiInfo(Context context){ ArrayList<WifiInfo> wifi = new ArrayList(); wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiInfo info = new WifiInfo(); info.mac = wm.getConnectionInfo().getBSSID(); wifi.add(info); return wifi; } }

调用google gears的方法,该方法调用gears来获取经纬度

private Location callGear(ArrayList<WifiInfo> wifi, ArrayList<CellIDInfo> cellID) { if (cellID == null) return null; DefaultHttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost( "http://www.google.com/loc/json"); JSONObject holder = new JSONObject(); try { holder.put("version", "1.1.0"); holder.put("host", "maps.google.com"); holder.put("home_mobile_country_code", cellID.get(0).mobileCountryCode); holder.put("home_mobile_network_code", cellID.get(0).mobileNetworkCode); holder.put("radio_type", cellID.get(0).radioType); holder.put("request_address", true); if ("460".equals(cellID.get(0).mobileCountryCode)) holder.put("address_language", "zh_CN"); else holder.put("address_language", "en_US"); JSONObject data,current_data; JSONArray array = new JSONArray(); current_data = new JSONObject(); current_data.put("cell_id", cellID.get(0).cellId); current_data.put("mobile_country_code", cellID.get(0).mobileCountryCode); current_data.put("mobile_network_code", cellID.get(0).mobileNetworkCode); current_data.put("age", 0); array.put(current_data); if (cellID.size() > 2) { for (int i = 1; i < cellID.size(); i++) { data = new JSONObject(); data.put("cell_id", cellID.get(i).cellId); data.put("location_area_code", cellID.get(0).locationAreaCode); data.put("mobile_country_code", cellID.get(0).mobileCountryCode); data.put("mobile_network_code", cellID.get(0).mobileNetworkCode); data.put("age", 0); array.put(data); } } holder.put("cell_towers", array); if (wifi.get(0).mac != null) { data = new JSONObject(); data.put("mac_address", wifi.get(0).mac); data.put("signal_strength", 8); data.put("age", 0); array = new JSONArray(); array.put(data); holder.put("wifi_towers", array); } StringEntity se = new StringEntity(holder.toString()); Log.e("Location send", holder.toString()); post.setEntity(se); HttpResponse resp = client.execute(post); HttpEntity entity = resp.getEntity(); BufferedReader br = new BufferedReader( new InputStreamReader(entity.getContent())); StringBuffer sb = new StringBuffer(); String result = br.readLine(); while (result != null) { Log.e("Locaiton reseive", result); sb.append(result); result = br.readLine(); } data = new JSONObject(sb.toString()); data = (JSONObject) data.get("location"); Location loc = new Location(LocationManager.NETWORK_PROVIDER); loc.setLatitude((Double) data.get("latitude")); loc.setLongitude((Double) data.get("longitude")); loc.setAccuracy(Float.parseFloat(data.get("accuracy").toString())); loc.setTime(AppUtil.getUTCTime()); return loc; } catch (JSONException e) { return null; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; }


目前已经测试过中国移动、联通的卡,以及测试过中兴的MIC,都可以准确定位。
不支持的是cdma,将cdma的数据传入到gears后返回的经纬度显示是在美国。

提外话,将gps和基站、wifi三者定位结合的话效果更好。基站的定位没有wifi准确,gps的定位速度比基站、wifi都来得更慢。

更多相关文章

  1. android收集应用崩溃信息
  2. Android和IOS获取crash信息
  3. 8大你不得不知的Android调试工具
  4. Android(安卓)NIO简易聊天室
  5. Android软件的自动更新
  6. Android之JNI续
  7. Android(安卓)MMS专题
  8. 关于 Android中googleMaps的Geocoder, “the service is not ava
  9. Android(安卓)断点续传的原理剖析与实例讲解

随机推荐

  1. Android(安卓)Canvas设置绘画时重叠部分
  2. android中如何显示图片的一部分
  3. Android代码规范+小技巧
  4. android 自定义TitleBar
  5. Android应用开发是否应避免使用枚举?
  6. Android提权漏洞分析——rageagainstthec
  7. IOS、Android自动化测试框架Appium概述
  8. Android-Module:AutoCompleteTextView常用
  9. android EditText获取光标位置并安插字符
  10. android > layout > background 背景图片