解决完了Android,下面应该就到了iPhone了。这个问题网上搜索的时候基本都是一个代码版本。
参考 iphone-wireless。
当然,我们实际上有三种方法可以获取,目前我并未在真机上面测试,本文先做整理,后会放出iPhone上的测试版本代码。
iPhone上基站信息获取可以采用如下三种方法:
1 iphone-wireless方式获取。
2 串口发送AT指令获取。
3 模拟电话拨号 *3001#12345#* 获取。
第一种方法参考
获取CELLID,LAC等信息方法,感谢tiger723和shixuehuiab兄的代码。这里仅摘录。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
//CoreTelephony.m
#import "CoreTelephony.h" #include <dlfcn.h> #import <UIKit/UIKit.h> #include <stdio.h> #include <stdlib.h> CFMachPortRef port ; struct CTServerConnection *sc =NULL ; //struct CTServerConnection scc; struct CellInfo cellinfo ; int b ; int t1 ; @implementation CoreTelephony int callback (CFNotificationCenterRef center , void *observer , CFStringRef name , const void *object , CFDictionaryRef userInfo ) { printf ( "Callback calledn" ) ; return 0 ; } - ( void ) getCellInfo { int cellcount ; char * sdk_path = "/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony" ; // void * dlopen( const char * pathname, int mode ); // 功能:以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。 打开错误返回NULL,成功,返回库引用 // RTLD_LAZY 暂缓决定,等有需要时再解出符号。这个参数使得未解析的symbol将在使用时去解析 int * handle =dlopen (sdk_path , RTLD_LAZY ) ; if (handle == NULL ) { return ; } // void* dlsym(void* handle,const char* symbol) 该函数在<dlfcn.h>文件中。将库中的一个函数绑定到预定义的函数地址(即获取到函数的指针)。handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数的名称,函数返回值是void*,指向函数的地址,供调用使用。 struct CTServerConnection * ( *CTServerConnectionCreate ) ( ) = dlsym (handle , "_CTServerConnectionCreate" ) ; sc =CTServerConnectionCreate (kCFAllocatorDefault , callback , &t1 ) ; // int (*CTServerConnectionGetPort)() = dlsym(handle, "_CTServerConnectionGetPort"); // port=CFMachPortCreateWithPort(kCFAllocatorDefault, _CTServerConnectionGetPort(sc), NULL, NULL, NULL); void ( *CTServerConnectionCellMonitorStart ) ( ) = dlsym (handle , "_CTServerConnectionCellMonitorStart" ) ; CTServerConnectionCellMonitorStart ( &t1 ,sc ) ; int * ( *CTServerConnectionCellMonitorGetCellCount ) ( ) = dlsym (handle , "_CTServerConnectionCellMonitorGetCellCount" ) ; CTServerConnectionCellMonitorGetCellCount ( &t1 ,sc ,&cellcount ) ; NSLog (@ "cellcount:%d" ,cellcount ) ; void ( *CTServerConnectionCellMonitorGetCellInfo ) ( ) = dlsym (handle , "_CTServerConnectionCellMonitorGetCellInfo" ) ; for ( int b = 0 ;b <cellcount ;b ++ ) { NSAutoreleasePool * pool = [ [NSAutoreleasePool alloc ] init ] ; memset ( &cellinfo , 0 , sizeof ( struct CellInfo ) ) ; int ts = 0 ; /** 这个方法的问题出现在这里,3.0以前的版本是4个参数,运行后会崩溃,后来发现新版本中是5个参数,不过获取的结果不理想,只获取了5个结果:MNC,MCC,LAC,CELLID,PXLEVEL,其他4项四项返回-1*/ CTServerConnectionCellMonitorGetCellInfo ( &t1 , sc , b , &ts , &cellinfo ) ; printf ( "Cell Site: %d, MNC: %d, " ,b ,cellinfo. servingmnc ) ; printf ( "LAC: %d, Cell ID: %d, Station: %d, " ,cellinfo. location , cellinfo. cellid , cellinfo. station ) ; printf ( "Freq: %d, RxLevel: %d, " , cellinfo. freq , cellinfo. rxlevel ) ; printf ( "C1: %d, C2: %dn" , cellinfo. c1 , cellinfo. c2 ) ; [pool release ] ; pool = nil ; } // 使用dlclose()来卸载打开的库 dlclose (handle ) ; } |
第二种方法同样参考自上篇文章:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include "at.h"
int fd = InitConn ( 115200 ) ; AT (fd ) ; char buf [ 100 ] = "" ; /** 这里是发送的AT命令,如下面的命令,可以获取CELL的一些信息, 还有其他的一些信息,网上找找就有了,不过不是所有的命令都可以用哦,有些iphone没有留接口,有就用到一个命令AT+CCED=0,1,这个可以获取CELL的较详细的信息,但是IPHONE就没有留接口,没法用,悲剧*/ //下面是一些我找到的,可以用的命令 //获取小区信息 //SendStrCmd(fd, "AT+CREG=2;+CREG?rn"); //获取当前小区的信号强度 //SendStrCmd(fd, "AT+CSQrn"); //基带信息 //SendStrCmd(fd, "At+xgendatarn"); //获得IMSI。这命令用来读取或者识别SIM卡的IMSI(国际移动签署者标识)。在读取IMSI之前应该先输入PIN(如果需要PIN的话)。 //SendStrCmd(fd, "AT+CCIDrn"); //获得SIM卡的标识。这个命令使模块读取SIM卡上的EF-CCID文件 //SendStrCmd(fd, "AT+CCIDrn"); //读取信息中心号码 //SendStrCmd(fd, "AT+CSCA?rn"); //单元广播信息标识。 //SendStrCmd(fd, "AT+CSCB?rn"); SendStrCmd (fd , "AT+XCELLINFO=1rn" ) ; while ( 1 ) { read (fd , buf , 100 ) ; printf ( "%s" , buf ) ; memset (buf , 0 , 100 ) ; } ; |
作者补充了代码:
at
另外,网上对以上方法做出了一些补充:
1. cellinfo的定义如下,估计就不会内存泄露了。
struct CellInfo
{
int mcc;
int mnc;
int location;
int cellid;
int station;
int freq;
int rxlevel;
int c1;
int c2;
int c3[6];
};
2.用AT命令取的话iphone4上试一下/dev/dlci.spi-baseband.extra_0。
3.也可能需要创造一个/tmp/ttydebugenable文件,然后 再/dev/tty.debug。
这个老帖子,现在还有人问,我也凑下热闹
代码没有问题,可以取到基站以及信号,但信号数字要减去-130或-110至于多少,需要你在查询相关资料
上面的代码只可以取到2G,信号,有些童鞋在实测发现,代码运行正常count一直是0,那是应该开着3G呢,至于3G怎么取我也在研究
AT指令确实可以取到比较丰富的信息,但在IPHONE4上应该是13楼所提到的文件dlci.spi-baseband.extra_0,但必须赋予+x权限,所以只能在开发试验使用,最终用户很难对权限进行更改
最后就是函数的问题,如果你是4.0以上的话,没有必要dlsym库里的函数,直接应用公开的库CoreTelephon.framwork即可,但需要声明下符号名称.
3 第三种方法
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
BOOL tryDial
(
)
{
NSString * rawNumber = [ [NSUserDefaults standardUserDefaults ] stringForKey : @ "phonenumber_preference" ] ; if (rawNumber && ! [rawNumber isEqualToString :@ "" ] ) { NSString * telNumber = @ "" ; for ( int i = 0 ; i < [rawNumber length ] ; i ++ ) { NSString * chr = [rawNumber substringWithRange :NSMakeRange (i , 1 ) ] ; if (doesStringContain (@ "*3001#12345#*" , chr ) ) { telNumber = [telNumber stringByAppendingFormat :@ "%@" , chr ] ; } } telNumber = [NSString stringWithFormat :@ "tel:%@" , telNumber ] ; [ [UIApplication sharedApplication ] openURL : [ [NSURL alloc ] initWithString :telNumber ] ] ; return TRUE ; } return FALSE ; } |
参考文章:
1 http://apt.weiphone.com/index.php?action=packageRead&id=9429
2 http://www.cocoachina.com/bbs/read.php?tid=70132
3 http://stackoverflow.com/questions/8846174/app-crash-at-ctserverconnectioncellmonitorgetcellinfo
4 http://www.devdiv.com/iOS_iPhone-iPhone%E4%B8%AD%E5%8F%96%E5%BE%97%E5%9F%BA%E7%AB%99%E7%9A%84cellid-thread-30564-1-1.html
5 http://www.cocoachina.com/downloads/video/2010/0713/1854.html
6 http://code.google.com/p/iphone-wireless/source/browse/trunk/CellStumbler/main.c
-End-