android可以借助于gps实现定位,但是很多地方是使用gps无法定位比如在室内,而且gps定位的话速度慢。
那么如何克服这样的缺点使得应用程序在室内也可以定位呢?办法是有的借助于基站和wifi进行定位。具体的细节可参考:
http://code.google.com/intl/zh-CN/apis/gears/geolocation_network_protocol.html
下面的代码实现了定位的大致功能
CellIDInfo.java 封装了cellid的信息
WifiInfo.java 封装了wifi的信息
CellIDInfoManager.java 可获取所有的CellIDInfo
WifiInfoManager.java 可获取wifi的信息,目前我只取了当前连接的wifi,没有获取所有能扫描到的wifi信息。
调用google gears的方法,该方法调用gears来获取经纬度
目前已经测试过中国移动、联通的卡,以及测试过中兴的MIC,都可以准确定位。
不支持的是cdma,将cdma的数据传入到gears后返回的经纬度显示是在美国。
那么如何克服这样的缺点使得应用程序在室内也可以定位呢?办法是有的借助于基站和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都来得更慢。
转自(http://fengzhizi715.iteye.com/blog/825716)