android可以借助于gps实现定位,但是很多地方是使用gps无法定位比如在室内,而且gps定位的话速度慢。
  那么如何克服这样的缺点使得应用程序在室内也可以定位呢?办法是有的借助于基站和wifi进行定位。具体的细节可参考:
  http://code.google.com/intl/zh-CN/apis/gears/geolocation_network_protocol.html
  下面的代码实现了定位的大致功能

  CellIDInfo.java 封装了cellid的信息
  Java代码
  public class CellIDInfo {
  public int cellId;
  public String mobileCountryCode;
  public String mobileNetworkCode;
  public int locationAreaCode;
  public String radioType;
  public CellIDInfo(){}
  }


  WifiInfo.java 封装了wifi的信息
  Java代码
  public class WifiInfo {
  public String mac;
  public WifiInfo(){}
  }


  CellIDInfoManager.java 可获取所有的CellIDInfo
  Java代码
  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 getCellIDInfo(Context context){
  manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
  listener = new PhoneStateListener();
  manager.listen(listener, 0);
  ArrayList CellID = new ArrayList();
  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 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;
  }
  }


  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 getCellIDInfo(Context context){
  manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
  listener = new PhoneStateListener();
  manager.listen(listener, 0);
  ArrayList CellID = new ArrayList();
  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 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信息。
  Java代码
  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 wifi = new ArrayList();
  wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
  WifiInfo info = new WifiInfo();
  info.mac = wm.getConnectionInfo().getBSSID();
  wifi.add(info);
  return 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 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来获取经纬度
  Java代码
  private Location callGear(ArrayList wifi,
  ArrayList 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;
  }
  private Location callGear(ArrayList wifi,
  ArrayList 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都来得更慢。


本文转载:CSDN博客