android GSM+CDMA基站定位--获取移动网络相关信息
本文转自:http://yunlonglove.iteye.com/blog/1560342
在googleAPI里提供了基站信息的获取类TelephonyManager,通过其方法getCellLocation得到CellLocation即可获取到基站相关信息
但CellLocation是个抽象类,所以在具体使用时需要判断接入的网络制式来用其子类CdmaCellLocation或GsmCellLocation来强转
CdmaCellLocation对应CDMA网,GsmCellLocation对应GSM网
三大网络运营商的网络制式对应如下:
移动2G 网 --> GSM
移动3G 网 --> TD-SCDMA
电信2G 网 --> CDMA
电信3G 网 --> CDMA2000
联通2G 网 --> GSM
联通3G 网 --> WCDMA
由此可见移动,联通2G 网都可使用GsmCellLocation
电信2G,3G网则使用CdmaCellLocation
那么移动3G和联通3G又当如何
其实经本人亲测,移动3G网也可使用GsmCellLocation,听说是TD-SCDMA衍生于GSM,具体原因咱也不用纠结了,反正能用就是了
而联通的WCDMA据说也可使用GsmCellLocation,那姑且就是这样吧,有条件的童鞋试一试吧。
对于网络制式的判断调用TelephonyManager.getNetworkType()可有多种情况,如下:
NETWORK_TYPE_UNKNOWN
NETWORK_TYPE_GPRS
NETWORK_TYPE_EDGE
NETWORK_TYPE_UMTS
NETWORK_TYPE_HSDPA
NETWORK_TYPE_HSUPA
NETWORK_TYPE_HSPA
NETWORK_TYPE_CDMA
NETWORK_TYPE_EVDO_0
NETWORK_TYPE_EVDO_A
NETWORK_TYPE_EVDO_B
NETWORK_TYPE_1xRTT
NETWORK_TYPE_IDEN
NETWORK_TYPE_LTE
NETWORK_TYPE_EHRPD
通过对网络类型判断后获取对应基站信息代码片段如下:
Html代码- publicstaticArrayList<CellIDInfo>getCellIDInfo(Contextcontext)throwsException{
- TelephonyManagermanager=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
- ArrayList<CellIDInfo>CellID=newArrayList<CellIDInfo>();
- CellIDInfocurrentCell=newCellIDInfo();
- inttype=manager.getNetworkType();
- Log.d(TAG,"getCellIDInfo-->NetworkType="+type);
- intphoneType=manager.getPhoneType();
- Log.d(TAG,"getCellIDInfo-->phoneType="+phoneType);
- if(type==TelephonyManager.NETWORK_TYPE_GPRS//GSM网
- ||type==TelephonyManager.NETWORK_TYPE_EDGE
- ||type==TelephonyManager.NETWORK_TYPE_HSDPA)
- {
- GsmCellLocationgsm=((GsmCellLocation)manager.getCellLocation());
- if(gsm==null)
- {
- Log.e(TAG,"GsmCellLocationisnull!!!");
- returnnull;
- }
- intlac=gsm.getLac();
- Stringmcc=manager.getNetworkOperator().substring(0,3);
- Stringmnc=manager.getNetworkOperator().substring(3,5);
- intcid=gsm.getCid();
- currentCell.cellId=gsm.getCid();
- currentCell.mobileCountryCode=mcc;
- currentCell.mobileNetworkCode=mnc;
- currentCell.locationAreaCode=lac;
- currentCell.radioType="gsm";
- CellID.add(currentCell);
- //获得邻近基站信息
- List<NeighboringCellInfo>list=manager.getNeighboringCellInfo();
- intsize=list.size();
- for(inti=0;i<size;i++){
- CellIDInfoinfo=newCellIDInfo();
- info.cellId=list.get(i).getCid();
- info.mobileCountryCode=mcc;
- info.mobileNetworkCode=mnc;
- info.locationAreaCode=lac;
- CellID.add(info);
- }
- }elseif(type==TelephonyManager.NETWORK_TYPE_CDMA//电信cdma网
- ||type==TelephonyManager.NETWORK_TYPE_1xRTT
- ||type==TelephonyManager.NETWORK_TYPE_EVDO_0
- ||type==TelephonyManager.NETWORK_TYPE_EVDO_A)
- {
- CdmaCellLocationcdma=(CdmaCellLocation)manager.getCellLocation();
- if(cdma==null)
- {
- Log.e(TAG,"CdmaCellLocationisnull!!!");
- returnnull;
- }
- intlac=cdma.getNetworkId();
- Stringmcc=manager.getNetworkOperator().substring(0,3);
- Stringmnc=String.valueOf(cdma.getSystemId());
- intcid=cdma.getBaseStationId();
- currentCell.cellId=cid;
- currentCell.mobileCountryCode=mcc;
- currentCell.mobileNetworkCode=mnc;
- currentCell.locationAreaCode=lac;
- currentCell.radioType="cdma";
- CellID.add(currentCell);
- //获得邻近基站信息
- List<NeighboringCellInfo>list=manager.getNeighboringCellInfo();
- intsize=list.size();
- for(inti=0;i<size;i++){
- CellIDInfoinfo=newCellIDInfo();
- info.cellId=list.get(i).getCid();
- info.mobileCountryCode=mcc;
- info.mobileNetworkCode=mnc;
- info.locationAreaCode=lac;
- CellID.add(info);
- }
- }
- returnCellID;
- }
从GOOGLE的API文档里总共有14钟网络类型,这里只罗列了其中7种,其他的主要是本人也不太清楚其对应到的网络制式是怎样的
所以部分童鞋的SIM卡网络制式不在这7种之内,自己根据实际情况看看它是归类于GSM还是CDMA在添进去就可以了
网络上多数教程是讲GSM网获取基站的,而忽略了C网的基站
这里我们可以比较一下GSM 和 CDMA 在获取基站信息时的不同之处
GSM:
int lac = gsm.getLac();
String mcc = manager.getNetworkOperator().substring(0, 3);
String mnc = manager.getNetworkOperator().substring(3, 5);
int cid = gsm.getCid();
CDMA:
int lac = cdma.getNetworkId();
String mcc = manager.getNetworkOperator().substring(0, 3);
String mnc = String.valueOf(cdma.getSystemId());
int cid = cdma.getBaseStationId();
在获取区域码LAC时GSM使用的是GsmCellLocation.getLac(),CDMA则用CdmaCellLocation.getNetworkId()来代替
在获取基站ID时GSM使用的是GsmCellLocation.getCid(),CDMA则用CdmaCellLocation.getBaseStationId()来代替
前面获取到的都是单个基站的信息,后面再获取周围邻近基站信息以辅助通过基站定位的精准性
TelephonyManager.getNeighboringCellInfo(),将其也放入基站信息LIST表中
最后通过google提供的gear接口获取经纬度,代码如下:
- publicstaticLocationcallGear(List<CellIDInfo>cellID){
- if(cellID==null||cellID.size()==0)
- returnnull;
- DefaultHttpClientclient=newDefaultHttpClient();
- HttpPostpost=newHttpPost("http://www.google.com/loc/json");
- JSONObjectholder=newJSONObject();
- 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");
- JSONObjectdata,current_data;
- JSONArrayarray=newJSONArray();
- current_data=newJSONObject();
- current_data.put("cell_id",cellID.get(0).cellId);
- current_data.put("location_area_code",cellID.get(0).locationAreaCode);
- 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);
- current_data.put("signal_strength",-60);
- current_data.put("timing_advance",5555);
- array.put(current_data);
- if(cellID.size()>2){
- for(inti=1;i<cellID.size();i++){
- data=newJSONObject();
- data.put("cell_id",cellID.get(i).cellId);
- data.put("location_area_code",cellID.get(i).locationAreaCode);
- data.put("mobile_country_code",cellID.get(i).mobileCountryCode);
- data.put("mobile_network_code",cellID.get(i).mobileNetworkCode);
- data.put("age",0);
- array.put(data);
- }
- }
- holder.put("cell_towers",array);
- StringEntityse=newStringEntity(holder.toString());
- Log.e("Locationsend",holder.toString());
- post.setEntity(se);
- HttpResponseresp=client.execute(post);
- HttpEntityentity=resp.getEntity();
- BufferedReaderbr=newBufferedReader(
- newInputStreamReader(entity.getContent()));
- StringBuffersb=newStringBuffer();
- Stringresult=br.readLine();
- while(result!=null){
- Log.e("Locaitonreseive-->",result);
- sb.append(result);
- result=br.readLine();
- }
- data=newJSONObject(sb.toString());
- data=(JSONObject)data.get("location");
- Locationloc=newLocation(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(System.currentTimeMillis());//AppUtil.getUTCTime());
- returnloc;
- }catch(JSONExceptione){
- e.printStackTrace();
- returnnull;
- }catch(UnsupportedEncodingExceptione){
- e.printStackTrace();
- }catch(ClientProtocolExceptione){
- e.printStackTrace();
- }catch(IOExceptione){
- e.printStackTrace();
- }
- returnnull;
- }
大家注意看这行holder.put("radio_type", cellID.get(0).radioType);
GSM就用"gsm",CDMA就用"cdma"
这个千万别搞混了,不然就获取不到信息了
值得一提的是C网获取基站再定位那偏差不是一般的大,是恨大,将近1千米了,大概是C网基站较少的缘故吧
最后通过经纬度获取地理位置信息,代码如下:
Java代码- publicstaticStringgetAddress(Locationitude)throwsException{
- StringresultString="";
- /**这里采用get方法,直接将参数加到URL上*/
- StringurlString=String.format("http://maps.google.cn/maps/geo?key=abcdefg&q=%s,%s",itude.getLatitude(),itude.getLongitude());
- Log.i("URL",urlString);
- /**新建HttpClient*/
- HttpClientclient=newDefaultHttpClient();
- /**采用GET方法*/
- HttpGetget=newHttpGet(urlString);
- try{
- /**发起GET请求并获得返回数据*/
- HttpResponseresponse=client.execute(get);
- HttpEntityentity=response.getEntity();
- BufferedReaderbuffReader=newBufferedReader(newInputStreamReader(entity.getContent()));
- StringBufferstrBuff=newStringBuffer();
- Stringresult=null;
- while((result=buffReader.readLine())!=null){
- strBuff.append(result);
- }
- resultString=strBuff.toString();
- Log.e("resultAdress--->",resultString);
- /**解析JSON数据,获得物理地址*/
- if(resultString!=null&&resultString.length()>0){
- JSONObjectjsonobject=newJSONObject(resultString);
- JSONArrayjsonArray=newJSONArray(jsonobject.get("Placemark").toString());
- resultString="";
- for(inti=0;i<jsonArray.length();i++){
- resultString=jsonArray.getJSONObject(i).getString("address");
- }
- }
- }catch(Exceptione){
- thrownewException("获取物理位置出现错误:"+e.getMessage());
- }finally{
- get.abort();
- client=null;
- }
- returnresultString;
- }
在获取地理位置的这个location事实上应该传入纠偏后的location,本文暂不做此处理,所以得到的地理信息位置是偶偏差的,大家注意
最后附上截图:
工程下载链接:http://download.csdn.net/detail/geniuseoe2012/4340303
更多相关文章
- Android(安卓)ionic工程中调用webrtc获取视频流
- Android(安卓)选择文件并获取路径
- /mnt/sdcard与Environment.getExternalStorageDirectory()的使用
- 几个比较混淆概念,android中的Info类以及PackageManager和Activit
- android media server 解析1-media player service 结构部分
- android中webview接收favicon总是获取为null解决方案
- 【笔记】Android上ROS开发——android_core创建一个android应用
- Android(安卓)打印日志封装库
- Android(安卓)PendingIntent