使用基站、wifi实现定位

阅读更多
    转载请注明出处
    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 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信息。
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来获取经纬度
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都来得更慢。

你可能感兴趣的:(Android,Mobile,Google,中兴,中国移动)