C# 使用Google API进行手机基站定位资料整理

 在网上收集了一部分关于使用Google API进行手机定位的资料和大家分享:

 关于基站定位方面的介绍:

http://tech.c114.net/164/a140837.html

开发方面的帮助:

http://www.dotblogs.com.tw/kylin/archive/2009/08/09/9964.aspx

http://code.google.com/intl/zh-CN/apis/maps/documentation/staticmaps/

http://www.codeproject.com/KB/mobile/DeepCast.aspx

http://heresy.spaces.live.com/blog/cns!E0070FB8ECF9015F!7866.entry?wa=wsignin1.0&sa=334916734

以上方法的流程一般如下:

通过RIL获取CellTowerInfo----->通过google api获取经纬度------->转换成54或是地方坐标后在地图上显示位置

 

本人整理了代码进行了测试,效果不是很好,使用的多普达S700,windows mobile 专业版 6.1 ,地点在上海,

定位结果如下

CELLID=1346
LAC=43060
MCC=460
MNC=0

从google获取的坐标31.109,121.368,定位位置到了莘西路上

经过计算与实际位置直线距离在8KM左右

 

而通过Google Maps在手机上测试当前位置提示精度为18000m,呵呵,这个精度恐怕只能确定在那个城市了,个人认为:原因可能有以下几点:

1.周围基站分布较少或是真的很远,上海的移动2G基站每年的数量都在减少,有时在公司的时候都会出现盲区,信号不是很好

2.直接通过cellid,lac,mcc,mnc等信息在Google上获取的经纬度没有经过误差分析,没有太大的精度可言

3.绕开中国移动运营商进行手机基站定位比较难,人家要靠这个赚钱的,当然也牵涉到国家安全,呵呵

4.RIL相关函数严格来说在Windows Mobile 上面都不是必须被实现的

下面是我的代码和注释,有些地方还是不能理解:

 

  1      public   class  RIL
  2      {
  3           // CellTower信息
  4           private   static   string  celltowerinfo  =   "" ;
  5 
  6           // 通过RIL获取CellID
  7           public   static   string  GetCellTowerInfo()
  8          {
  9               // 初始化句柄
 10              IntPtr hRil  =  IntPtr.Zero;
 11              IntPtr hRes  =  IntPtr.Zero;
 12 
 13               // 初始化结果变量
 14              celltowerinfo  =   "" ;
 15 
 16               // 为一个Client初始化RIL    
 17              hRes  =  RIL_Initialize( 1 ,
 18                                  new  RILRESULTCALLBACK(rilResultCallBack),
 19                                  null ,
 20                                  0 ,
 21                                  0 ,
 22                                  out  hRil);
 23 
 24               if  (hRes  !=  IntPtr.Zero)
 25              {
 26                   return   " 不能初始化RIL " ;
 27              }
 28 
 29               // 获取当前Phone使用的基站信息
 30              hRes  =  RIL_GetCellTowerInfo(hRil);
 31 
 32              waithandle.WaitOne();
 33 
 34               // 解除RIL
 35              RIL_Deinitialize(hRil);
 36 
 37               return  celltowerinfo;
 38 
 39 
 40          }
 41 
 42           private   static  AutoResetEvent waithandle  =   new  AutoResetEvent( false );
 43 
 44           public   static   void  rilResultCallBack( uint  dwCode, 
 45                                               IntPtr hrCmdID, 
 46                                               IntPtr lpData, 
 47                                                uint  cdData, 
 48                                                uint  dwParam)
 49          {
 50              RILCELLTOWERINFO rilCellTowerInfo  =   new  RILCELLTOWERINFO();
 51 
 52               // 将数据lpData从非托管内存块封送到rilCellTowerInfo托管对象中
 53              Marshal.PtrToStructure(lpData, rilCellTowerInfo);
 54 
 55              celltowerinfo  =  rilCellTowerInfo.dwCellID  +   " - "   +  rilCellTowerInfo.dwLocationAreaCode  +   " - "   +
 56                              rilCellTowerInfo.dwMobileCountryCode + " - " + rilCellTowerInfo.dwMobileNetworkCode;
 57                 
 58               // 将事件状态设置为终止状态,允许一个或多个等待线程继续
 59              waithandle.Set();
 60          }
 61          
 62           public   delegate   void  RILRESULTCALLBACK( uint  dwCode,IntPtr hrCmdID,IntPtr lpData, uint  cbData, uint  dwParam);
 63 
 64           public   delegate   void  RILNOTIFYCALLBACK( uint  dwCode,IntPtr lpData, uint  cbData, uint  dwParam);
 65 
 66           // RIL基站信息类
 67           public   class  RILCELLTOWERINFO
 68          {
 69                  public   uint  cbSize;  
 70                  public   uint  dwParams;  
 71                  public   uint  dwMobileCountryCode;  
 72                  public   uint  dwMobileNetworkCode;  
 73                  public   uint  dwLocationAreaCode;  
 74                  public   uint  dwCellID;  
 75                  public   uint  dwBaseStationID;  
 76                  public   uint  dwBroadcastControlChannel;  
 77                  public   uint  dwRxLevel;  
 78                  public   uint  dwRxLevelFull;  
 79                  public   uint  dwRxLevelSub;  
 80                  public   uint  dwRxQuality;  
 81                  public   uint  dwRxQualityFull;  
 82                  public   uint  dwRxQualitySub;  
 83                  public   uint  dwIdleTimeSlot;  
 84                  public   uint  dwTimingAdvance;  
 85                  public   uint  dwGPRSCellID;  
 86                  public   uint  dwGPRSBaseStationID;  
 87                  public   uint  dwNumBCCH;  
 88 
 89 
 90          }
 91 
 92           /*  调用API    
 93           * 初始化RIL    
 94           * MSDN:    http://msdn.microsoft.com/zh-cn/library/aa919106 (en-us).aspx  */
 95          [DllImport( " ril.dll " )]
 96           private   static   extern  IntPtr RIL_Initialize( uint  dwIndex, RILRESULTCALLBACK pfnResult, RILNOTIFYCALLBACK pfnNotify,  uint  dwNotificationClasses,  uint  dwParam,  out  IntPtr lphRil);
 97          [DllImport( " ril.dll " )]
 98           private   static   extern  IntPtr RIL_GetCellTowerInfo(IntPtr hRil);
 99          [DllImport( " ril.dll " )]
100           private   static   extern  IntPtr RIL_Deinitialize(IntPtr hRil);
101 
102      }

 

之后是有关通信方面的,通过基站信息获取经纬度(GOOGLE API)

 

ExpandedBlockStart.gif 代码
   public   class  GMM
    {     
          
static   byte [] PostData( int  MCC,  int  MNC,  int  LAC,  int  CID,  
                               
bool  shortCID)  
      { 
           
            
byte [] pd  =   new   byte []{  
                
0x00 0x0e ,  
                
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ,  
                
0x00 0x00 ,  
                
0x00 0x00 ,  
                
0x00 0x00 ,  
 
                
0x1b ,  
                
0x00 0x00 0x00 0x00 //  Offset 0x11  
                 0x00 0x00 0x00 0x00 //  Offset 0x15  
                 0x00 0x00 0x00 0x00 //  Offset 0x19  
                 0x00 0x00 ,  
                
0x00 0x00 0x00 0x00 //  Offset 0x1f  
                 0x00 0x00 0x00 0x00 //  Offset 0x23  
                 0x00 0x00 0x00 0x00 //  Offset 0x27  
                 0x00 0x00 0x00 0x00 //  Offset 0x2b  
                 0xff 0xff 0xff 0xff ,  
                
0x00 0x00 0x00 0x00   
            };  
 
            
bool  isUMTSCell  =  ((Int64)CID  >   65535 );  
 
            
if  (isUMTSCell)  
                Console.WriteLine(
" UMTS CID.{0} " , shortCID  ?   
                 
" Using short CID to resolve. "  :  "" );  
            
else   
                Console.WriteLine(
" GSM CID given. " );  
 
            
if  (shortCID)  
                CID 
&=   0xFFFF ;       /*  Attempt to resolve the cell using the    
 
            if ((Int64)CID > 65536) /* GSM: 4 hex digits, UTMS: 6 hex  
                                    digits 
*/
            
if  ((Int64)CID  >   65536 )
                pd[
0x1c =   5 ;  
            
else   
                pd[
0x1c =   3 ;  
 
            pd[
0x11 =  ( byte )((MNC  >>   24 &   0xFF );  
            pd[
0x12 =  ( byte )((MNC  >>   16 &   0xFF );  
            pd[
0x13 =  ( byte )((MNC  >>   8 &   0xFF );  
            pd[
0x14 =  ( byte )((MNC  >>   0 &   0xFF );  
 
            pd[
0x15 =  ( byte )((MCC  >>   24 &   0xFF );  
            pd[
0x16 =  ( byte )((MCC  >>   16 &   0xFF );  
            pd[
0x17 =  ( byte )((MCC  >>   8 &   0xFF );  
            pd[
0x18 =  ( byte )((MCC  >>   0 &   0xFF );  
 
            pd[
0x27 =  ( byte )((MNC  >>   24 &   0xFF );  
            pd[
0x28 =  ( byte )((MNC  >>   16 &   0xFF );  
            pd[
0x29 =  ( byte )((MNC  >>   8 &   0xFF );  
            pd[
0x2a =  ( byte )((MNC  >>   0 &   0xFF );  
 
            pd[
0x2b =  ( byte )((MCC  >>   24 &   0xFF );  
            pd[
0x2c =  ( byte )((MCC  >>   16 &   0xFF );  
            pd[
0x2d =  ( byte )((MCC  >>   8 &   0xFF );  
            pd[
0x2e =  ( byte )((MCC  >>   0 &   0xFF );  
 
            pd[
0x1f =  ( byte )((CID  >>   24 &   0xFF );  
            pd[
0x20 =  ( byte )((CID  >>   16 &   0xFF );  
            pd[
0x21 =  ( byte )((CID  >>   8 &   0xFF );  
            pd[
0x22 =  ( byte )((CID  >>   0 &   0xFF );  
 
            pd[
0x23 =  ( byte )((LAC  >>   24 &   0xFF );  
            pd[
0x24 =  ( byte )((LAC  >>   16 &   0xFF );  
            pd[
0x25 =  ( byte )((LAC  >>   8 &   0xFF );  
            pd[
0x26 =  ( byte )((LAC  >>   0 &   0xFF );  
 
            
return  pd;  
        }
                                    
// GSM CID part */  
 
       
///  
       
///  通过基站信息获取经纬度
       
///  

       
///  
       
///  
         static   public   string  GetLatLng( string [] args)  
       {  
            
if  (args.Length  <   4 )  
            {  
                
return   string .Empty;  
            }  
            
string  shortCID  =   "" ;    /*  Default, no change at all  */   
            
if  (args.Length  ==   5 )  
                shortCID 
=  args[ 4 ].ToLower();  
            
try   
            {  
                String url 
=   " http://www.google.com/glm/mmap " ;  
                HttpWebRequest req 
=  (HttpWebRequest)WebRequest.Create(  
                    
new  Uri(url));  
                req.Method 
=   " POST " ;  
 
                
int  MCC  =  Convert.ToInt32(args[ 0 ]);  
                
int  MNC  =  Convert.ToInt32(args[ 1 ]);  
                
int  LAC  =  Convert.ToInt32(args[ 2 ]);  
                
int  CID  =  Convert.ToInt32(args[ 3 ]);  
                
byte [] pd  =  PostData(MCC, MNC, LAC, CID,  
                    shortCID 
==   " shortcid " );  
 
                req.ContentLength 
=  pd.Length;  
                req.ContentType 
=   " application/binary " ;  
                Stream outputStream 
=  req.GetRequestStream();  
                outputStream.Write(pd, 
0 , pd.Length);  
                outputStream.Close();  
 
                HttpWebResponse res 
=  (HttpWebResponse)req.GetResponse();  
                
byte [] ps  =   new   byte [res.ContentLength];  
                
int  totalBytesRead  =   0 ;  
                
while  (totalBytesRead  <  ps.Length)  
                {  
                    totalBytesRead 
+=  res.GetResponseStream().Read(  
                        ps, totalBytesRead, ps.Length 
-  totalBytesRead);  
                }  
 
                
if  (res.StatusCode  ==  HttpStatusCode.OK)  
               {  
                    
short  opcode1  =  ( short )(ps[ 0 <<   8   |  ps[ 1 ]);  
                    
byte  opcode2  =  ps[ 2 ];  
                    
int  ret_code  =  ( int )((ps[ 3 <<   24 |  (ps[ 4 <<   16 |   
                                   (ps[
5 <<   8 |  (ps[ 6 ]));  
                    
if  (ret_code  ==   0 )  
                  {  
                        
double  lat  =  (( double )((ps[ 7 <<   24 |  (ps[ 8 <<   16 )  
                                     
|  (ps[ 9 <<   8 |  (ps[ 10 ])))  /   1000000 ;  
                        
double  lon  =  (( double )((ps[ 11 <<   24 |  (ps[ 12 <<   
                                     
16 |  (ps[ 13 <<   8 |  (ps[ 14 ])))  /   
                                     
1000000 ;  
                        
return  lat  +   " | "   +  lon;  
                    }  
                    
else   
                        
return   string .Empty;  
                }  
                
else   
                    
return   string .Empty;  
            }  
            
catch  (Exception ex)  
            {  
                MessageBox.Show(ex.ToString());  
                
return   string .Empty;  
            }  
        }  

    }

 

下面在介绍一种只要知道cellid和lac两个参数就可以获取经纬度的方法:

 

 1    ///  
 2           ///  判断是否正确获取经纬度信息
 3           ///  

 4           ///   cellid
 5           ///   LocationAreaCode
 6           ///   latitude
 7           ///   longgitude
 8           ///  
 9           public   static   bool  LocateGooleMapApi( uint  cellid,  uint  lac,  out   double  Lat,  out   double  Lng)
10          {
11              HttpWebRequest request  = (HttpWebRequest)WebRequest.Create( " http://www.google.com/glm/mmap " );
12              request.Method  =   " POST " ;
13 
14           
15               byte [] byteArray  =  { 0x00 , 0x15 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x02
16                           0x65 0x6E //  en
17                           0x00 0x07
18                           0x41 0x6E 0x64 0x72 0x6F 0x69 0x64
19                           0x00 0x03
20                           0x31 0x2E 0x30 //  1.0
21                           0x00 0x03
22                           0x57 0x65 0x62 //  web
23                           0x1B , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
24                           0x00 , 0x00 , 0x00 , 0x00 , 0x03 , 0x00 , 0x00
25                           0xFF 0xFF 0xFF 0xFF //  CellID
26                           0xFF 0xFF 0xFF 0xFF //  LAC
27                           0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
28                           0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00  };
29 
30               //  write CellID
31               byte [] intByte  =  BitConverter.GetBytes(cellid);
32              byteArray[ 48 =  intByte[ 3 ];
33              byteArray[ 49 =  intByte[ 2 ];
34              byteArray[ 50 =  intByte[ 1 ];
35              byteArray[ 51 =  intByte[ 0 ];
36 
37               //  write LAC
38              intByte  =  BitConverter.GetBytes(lac);
39              byteArray[ 52 =  intByte[ 3 ];
40              byteArray[ 53 =  intByte[ 2 ];
41              byteArray[ 54 =  intByte[ 1 ];
42              byteArray[ 55 =  intByte[ 0 ];
43 
44               //  set request
45              request.ContentLength  =  byteArray.Length;
46              Stream postStream  =  request.GetRequestStream();
47              postStream.Write(byteArray,  0 , byteArray.Length);
48              postStream.Close();
49 
50               //  Get the response.
51              HttpWebResponse response  =  (HttpWebResponse)request.GetResponse();
52              Console.WriteLine( " [I] Request response: {0} " , response.StatusDescription);
53 
54               //  Read response
55              Stream dataStream  =  response.GetResponseStream();
56              BinaryReader BR  =   new  BinaryReader(dataStream);
57               //  skip 3 byte
58              BR.ReadByte();
59              BR.ReadByte();
60              BR.ReadByte();
61 
62               //  check state
63               if  ( 0   ==  BR.ReadInt32())
64              {
65                   //  read lat
66                   byte [] tmpByte  =   new   byte [ 4 ];
67                  tmpByte[ 3 =  BR.ReadByte();
68                  tmpByte[ 2 =  BR.ReadByte();
69                  tmpByte[ 1 =  BR.ReadByte();
70                  tmpByte[ 0 =  BR.ReadByte();
71                  Lat  =  ( double )(BitConverter.ToInt32(tmpByte,  0 ))  /  1000000D;
72 
73                   //  read lng
74                  tmpByte[ 3 =  BR.ReadByte();
75                  tmpByte[ 2 =  BR.ReadByte();
76                  tmpByte[ 1 =  BR.ReadByte();
77                  tmpByte[ 0 =  BR.ReadByte();
78                  Lng  =  ( double )(BitConverter.ToInt32(tmpByte,  0 ))  /  1000000D;
79 
80                  BR.Close();
81                  dataStream.Close();
82                  response.Close();
83                   return   true ;
84              }
85               else
86              {
87                  BR.Close();
88                  dataStream.Close();
89                  response.Close();
90                  Lat  =   0 ;
91                  Lng  =   0 ;
92                   return   false ;
93              }
94 
95 
96          }

 

最后只要用C#2008 建立一个新项目,添加webbrowser控件,添加一个按键代码如下:

 

 1        Cursor.Current  =  Cursors.WaitCursor;
 2               string  [] cellidFields  =  RIL.GetCellTowerInfo().ToString().Split( ' - ' );
 3                
 4               string [] args  = {
 5                                 cellidFields[ 2 ],
 6                                  " 0 " ,
 7                                 cellidFields[ 1 ],
 8                                 cellidFields[ 0 ]
 9                             };
10               string [] latlng  =  GMM.GetLatLng(args).Split( ' | ' );
11 
12              Uri url  =   new  Uri( " http://maps.google.com/staticmap?&maptype=satellite&key=xxx&markers= "   +  latlng[ 0 ].ToString().Replace( ' , ' ' . ' +   " , "   +  latlng[ 1 ].ToString().Replace( ' , ' ' . ' +   " ¢er=,&size=240x320&zoom=18 " );
13              webBrowser1.Navigate(url);
14              Cursor.Current  =  Cursors.Default;

 

 

就只有这些了,如果谁有更好的利用GOOGLE 进行手机基站定位,精度较高的方法,请告诉我,本人不胜感激啊!

 

 

转载于:https://www.cnblogs.com/MyLucifer/archive/2010/02/25/1673587.html

你可能感兴趣的:(C# 使用Google API进行手机基站定位资料整理)