IOS 获取设备相关特性
一、 判断手机是否插入了SIM卡
解答:
A. 私有 API 检测
[CTSIMSupportGetSIMStatus()isEqualToString:kCTSIMSupportSIMStatusNotInserted] 可以判断是否插入了 sim 卡。
前提是把下面的代码随便复制到一个头文件里面,然后引入CoreTelephony.framework 即可。
1 extern NSString* c*****tkCTSMSMessageReceivedNotification;
2
3 extern NSString* c*****tkCTSMSMessageReplaceReceivedNotification;
4
5 extern NSString* c*****tkCTSIMSupportSIMStatusNotInserted;
6
7 extern NSString* c*****t kCTSIMSupportSIMStatusReady;
8
9
10 id CTTelephonyCenterGetDefault(void);
11
12 void CTTelephonyCenterAddObserver(id,id,CFNotificationCallback,NSString*,void*,int);
13
14 voidCTTelephonyCenterRemoveObserver(id,id,NSString*,void*);
15
16 int CTSMSMessageGetUnreadCount(void);
17
18 int CTSMSMessageGetRecordIdentifier(void * msg);
19
20 NSString * CTSIMSupportGetSIMStatus();
21
22 NSString * CTSIMSupportCopyMobileSubscriberIdentity();
23
24 id CTSMSMessageCreate(void* unknow,NSString*number,NSString* text);
25
26 void * CTSMSMessageCreateReply(void* unknow,void *forwardTo,NSString* text);
27
28 void* CTSMSMessageSend(id server,id msg);
29
30 NSString *CTSMSMessageCopyAddress(void *, void *);
31
32 NSString *CTSMSMessageCopyText(void *, void *);
B. 开放 API 检测(有待改进,飞行模式下检测不到)
1 -(BOOL)simExist {
2
3 CTTelephonyNetworkInfo *info =[[CTTelephonyNetworkInfo alloc] init];
4
5 CTCarrier *carrier = [info subscriberCellularProvider];
6
7 //NSString *code = [carriermobileNetworkCode];
8
9 NSString *isoCountryCode =[carrier isoCountryCode];
10
11 if (isoCountryCode == nil ||isoCountryCode.length == 0) {
12
13 NSLog(@"no sim");
14
15 return NO;
16 } else {
17
18 NSLog(@"sim exist");
19
20 return YES;
21 }
22 }
二、 获取更换 SIM卡后的通知(只有更换前后的 SIM 运营商不同才能收到)
解答:
1 //初始化
2 CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
3
4 //当sim卡更换时弹出此窗口
5 networkInfo.subscriberCellularProviderDidUpdateNotifier = ^(CTCarrier *carrier) {
6
7 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"Sim card changed" delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
8
9 [alert show];
10 };
三、 获取 SIM卡信息
解答:
1 //初始化
2 CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
3
4 //获取sim卡信息
5 CTCarrier *carrier = networkInfo.subscriberCellularProvider;
6
7 //供应商名称(中国联通 中国移动)
8 carrier.carrierName;
9
10 //所在国家编号
11 carrier.mobileCountryCode;
12
13 //供应商网络编号
14 carrier.mobileNetworkCode;
15
16 // iso 国家编号
17 carrier.isoCountryCode;
18
19 //是否允许voip
20 carrier.allowsVOIP;
四、 判断锁屏状态
解答:
A. 私有 API 检测
1 #import <SpringBoard/SBAwayController.h>
2
3 //一句话搞定
4 if ([[objc_getClass("SBAwayController")sharedAwayController] isLocked]) {
5
6 PrintLog(@"doublecheck Home ,now YES Lock");
7 } else {
8
9 PrintLog(@"double check Home ,now NOLock");
10 }
B. 程序在前台,这种比较简单。直接使用Darwin层的通知就可以了
1 #import <notify.h>
2
3 #define NotificationLockCFSTR("com.apple.springboard.lockcomplete")
4 #define NotificationChangeCFSTR("com.apple.springboard.lockstate")
5 #define NotificationPwdUICFSTR("com.apple.springboard.hasBlankedScreen")
6
7
8 static voidscreenLockStateChanged(CFNotificationCenterRef center,void*observer,CFStringRef name,const void* object,CFDictionaryRef userInfo) {
9
10 NSString*lockstate = (__bridge NSString*)name;
11
12 if ([lockstateisEqualToString:(__bridge NSString*)NotificationLock]) {
13
14 NSLog(@"locked.");
15 } else {
16
17 NSLog(@"lock state changed.");
18 }
19 }
20
21
22 - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
23
24 // Overridepoint for customization after application launch.
25 CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),NULL, screenLockStateChanged, NotificationLock, NULL,CFNotificationSuspensionBehaviorDeliverImmediately);
26
27 CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),NULL, screenLockStateChanged, NotificationChange, NULL,CFNotificationSuspensionBehaviorDeliverImmediately);
28
29 //setScreenStateCb();
30 return YES;
31 }
C. 程序退后台后,这时再锁屏就收不到上面的那个通知了,需要另外一种方式, 以循环的方式一直来检测是否是锁屏状态,会消耗性能并可能被苹果挂起
1 static voidsetScreenStateCb() {
2
3 uint64_tlocked;
4
5 __block inttoken = 0;
6
7 notify_register_dispatch("com.apple.springboard.lockstate",&token,dispatch_get_main_queue(),^(intt) {
8 });
9
10 notify_get_state(token, &locked);
11
12 NSLog(@"%d",(int)locked);
13 }
14
15
16 -(void)applicationDidEnterBackground:(UIApplication *)application {
17
18 while (YES) {
19
20 setScreenStateCb();
21
22 sleep(1);
23 }
24 }
关于 notify.h 请移步到:
五、 获取电池状态(是否正在充电)
解答:
通过 UIDeviceBatteryStateDidChangeNotification 通知可以获取手机是否处于充电状态。
1 (void)batteryMoniter {
2
3 UIDevice *device = [UIDevice currentDevice];
4
5 device.batteryMonitoringEnabled = YES;
6
7 if (device.batteryState == UIDeviceBatteryStateUnknown) {
8
9 NSLog(@"UnKnow");
10 }else if (device.batteryState == UIDeviceBatteryStateUnplugged){
11
12 NSLog(@"Unplugged");
13 }else if (device.batteryState == UIDeviceBatteryStateCharging){
14
15 NSLog(@"Charging");
16 }else if (device.batteryState == UIDeviceBatteryStateFull){
17
18 NSLog(@"Full");
19 }
20
21 NSLog(@"%f",device.batteryLevel);
22 }
六、 获取电池电量
解答:
1 UIDevice *device = [UIDevice currentDevice];
2
3 device.batteryMonitoringEnabled = YES;
4
5 NSLog(@"%f",device.batteryLevel);//简单的这句就是了。
6
7 ################################################
8
9 Having said that, I would not use a timer event for this, it is pretty inefficient. You want to use KVO instead:
10
11 - (void) viewWillAppear:(BOOL)animated {
12
13 UIDevice *device = [UIDevice currentDevice];
14
15 device.batteryMonitoringEnabled = YES;
16
17 currentCharge.text = [NSString stringWithFormat:@"%.2f", device.batteryLevel];
18
19 [device addObserver:self forKeyPath:@"batteryLevel" options:0x0 context:nil];
20
21 [super viewWillAppear:animated];
22 }
23
24
25 - (void) viewDidDisappear:(BOOL)animated {
26
27 UIDevice *device = [UIDevice currentDevice];
28
29 device.batteryMonitoringEnabled = NO;
30
31 [device removeObserver:self forKeyPath:@"batteryLevel"];
32
33 [super viewDidDisappear:animated];
34 }
35
36
37 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
38
39 UIDevice *device = [UIDevice currentDevice];
40
41 if ([object isEqual:device] && [keyPath isEqual:@"batteryLevel"]) {
42
43 currentCharge.text = [NSString stringWithFormat:@"%.2f", device.batteryLevel];
44
45 }
46 }
EAAccessory相关方法需要Iphone的外设配件支持,只有在配件通过30pin、蓝牙、USB的方式连接iOS设备时,才能够通过该方法来检测是否连接(外设配件)的状态。外设的相关设置,需要在info.plist中添加UISupportedExternalAccessoryProtocols键,需要把pc端设置成iPhone的外设备才行,这一步不知道怎么做了。
七、 获取 SIM 卡信号强度
解答:
私有 API 获取
1 intgetSignalStrength() {
2
3 void *libHandle =dlopen("/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony",RTLD_LAZY);
4
5 int (*CTGetSignalStrength)();
6
7 CTGetSignalStrength = dlsym(libHandle,"CTGetSignalStrength");
8
9 if( CTGetSignalStrength == NULL) {
10
11 NSLog(@"Couldnot find CTGetSignalStrength");
12 }
13
14 int result = CTGetSignalStrength();
15
16 dlclose(libHandle);
17 return result;
18 }
以上代码获取 RSSI 的值为正,函数拿到的是 rssi,转换成 dbm 需要剪掉 113
可以用class-dump这个工具来导出库里的头文件结构(包含了私有API)
八、 获取 WIFI 的信息(WIFI列表和强度)
解答:
1 - (id)fetchSSIDInfo {
2
3 NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
4
5 NSLog(@"Supported interfaces: %@", ifs);
6
7 id info = nil;
8
9 for (NSString *ifnam in ifs) {
10
11 info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
12
13 NSLog(@"%@ => %@", ifnam, info);
14
15 if (info && [info count]) { break; }
16 }
17
18 return info;
19 }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/zrhloveswallow/article/details/47808239