IOS 获取设备相关特性

来源:互联网 发布:js内置对象有哪些 编辑:程序博客网 时间:2024/06/15 16:04

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 请移步到:

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/notify_register_check.3.html

 

五、 获取电池状态(是否正在充电)

解答:

通过 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  }

 

http://stackoverflow.com/questions/6161318/how-to-determine-whether-ios-device-is-connected-to-desktop-computer-and-itunes

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  }

 

九、  判断当前应用的定位服务是否可用

解答:

用到地图定位的时候,会判断定位是否可用来初始化定位服务。但是以前的方法是判断所有应用的定位服务,无法指定到当前的应用是否开启服务。下面的就可以直接搞定这个问题。

1    //[CLLocationManager locationServicesEnabled]判断全局的定位功能是否可用

2    if ([CLLocationManager locationServicesEnabled] && ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined)) {  

3     

4        //定位功能可用,开始定位  

5        _locationManger = [[CLLocationManager alloc] init]; 

6     

7         locationManger.delegate = self;  

8     

9         [locationManger startUpdatingLocation];  

10  else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied){  

11   

12       NSlog("定位功能不可用,提示用户或忽略");   

13  }

 

十、  监测网络状态的改变

解答:

1    -(void)startNetCheck {

2     

3         NSLog(@"探测网络开始,startNetCheck");

4         

5         [AFNetworkReachabilityManagermanagerForDomain:@"www.baidu.com"];

6      

7         [[AFNetworkReachabilityManagersharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatusstatus) {

8      

9             NSLog(@"探测网络结果[%d]",status);

10    

11           //发送通知

12           [[NSNotificationCenterdefaultCenter]postNotificationName:RcSGlobalNoticeNetworkChangeobject:@(status)];

13       }];

14    

15       [[AFNetworkReachabilityManagersharedManager] startMonitoring];

16  }

 

十一、  监测蓝牙开启状态

解答:

添加类库:

CoreBluetooth.framework

      

导入:

#import<CoreBluetooth/CoreBluetooth.h>

      

初始化并设置代理:

CBCentralManager*centralManager = [[CBCentralManager alloc] initWithDelegate:selfqueue:nil];  

      

实现代码方法:

1    -(void)peripheralManagerDidUpdateState:(CBPeripheralManager*)peripheral {

2     

3        switch (peripheral.state) {

4     

5             //蓝牙开启且可用

6                caseCBPeripheralManagerStatePoweredOn: {

7     

8                      NSLog(@"Bluetoothis currently powered on and available to use.");

9                }

10              break

11              default:

12   

13                    NSLog(@"PeripheralManager did change state");

14   

15             break;

16      }

17  }

 

十二、  红外感应(距离感应器)

解答:

1    - (void)handleNotification:(BOOL)state{

2     

3        [[UIDevicecurrentDevice]setProximityMonitoringEnabled:state];//设置红外感应是否可用

4        

5        if(state) {//添加监听

6     

7            [[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(sensorStateChange:) name:@"UIDeviceProximityStateDidChangeNotification"object:nil];

8        }else {//移除监听

9     

10          [[NSNotificationCenterdefaultCenter]removeObserver:self name:@"UIDeviceProximityStateDidChangeNotification"object:nil];

11  }

12   

13  //处理监听触发事件

14  -(void)sensorStateChange:(NSNotificationCenter*)notification {

15   

16      //如果此时手机靠近面部放在耳朵旁,那么声音将通过听筒输出,并将屏幕变暗(省电啊)

17      if([[UIDevicecurrentDevice]proximityState]== YES) {

18   

19          NSLog(@"Deviceis close to user");

20   

21          [[AVAudioSessionsharedInstance]setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];

22      }else{

23   

24          NSLog(@"Deviceis not close to user");

25   

26          [[AVAudioSessionsharedInstance]setCategory:AVAudioSessionCategoryPlayback error:nil];

27      }

28  }

 

十三、  监听程序失去active(比如 按下home键)和成为active

解答:

第一步:

创建2个NSNotificationCenter监听

1.  [[NSNotificationCenterdefaultCenter] addObserver:self selector:@selector(applicationWillResignActive:)name:UIApplicationWillResignActiveNotificationobject:nil];//监听是否触发home键挂起程序

2.      

3.  [[NSNotificationCenterdefaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:)name:UIApplicationDidBecomeActiveNotificationobject:nil];//监听是否重新进入程序程序

 

第二步:

实现2个NSNotificationCenter所触发的事件方法

1.  (void)applicationWillResignActive:(NSNotification*)notification{

2.   

3.      printf("按理说是触发home按下\n");

4.  }

5.   

6.  -(void)applicationDidBecomeActive:(NSNotification*)notification{

7.   

8.      printf("按理说是重新进来后响应\n");

9.  }

 

十四、  监听输出设备变化(耳机插拔、蓝牙设备断与连)

解答:

ios6以前,我们有如下的方法:

      

1.       #import<AVFoundation/AVFoundation.h>

2.        

3.       [[AVAudioSession sharedInstance] setDelegate:self];

4.        

5.       AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange,audioRouteChangeListenerCallback, self);

 

然后实现该回调:

 

1.      //音频监控回调函数

2.      static void audioRouteChangeListenerCallback(void *inUserData, AudioSessionPropertyID inPropertyID, UInt32inPropertyValueSize, const void *inPropertyValue) {

3.       

4.      if (inPropertyID != kAudioSessionProperty_AudioRouteChange){

5.       

6.         return;

7.      }

8.      // Determines the reason for the routechange, to ensure that it is not

9.      // because of a category change.

10.    

11.   CFDictionaryRef routeChangeDictionary =inPropertyValue;

12.    

13.   CFNumberRef routeChangeReasonRef =CFDictionaryGetValue (routeChangeDictionary, CFSTR (kAudioSession_AudioRouteChangeKey_Reason));

14.    

15.   SInt32         routeChangeReason;

16.    

17.   CFNumberGetValue (routeChangeReasonRef,kCFNumberSInt32Type,&routeChangeReason);

18.   //  do your handling here

19.   }

 

请注意[[AVAudioSession sharedInstancesetDelegate:self]一定不要遗漏,否则该回调应该无法触发。

 

--------------分割线--------------

 

上面的方法是ios6以前的实现方式,我们可以看出这个api是比较低级的实现,其回调还是c的实现方式,而不是我们平常习惯的oc实现。

 

因此在ios6及以后,上面的apideprecated了(当然,你要是还这么用,也还是能够实现功能),我们有更好更高级的实现来解决问题:

 

1.       [[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(outputDeviceChanged:)name:AVAudioSessionRouteChangeNotificationobject:[AVAudioSessionsharedInstance]];

2.        

3.       -(void)outputDeviceChanged:(NSNotification *)aNotification {

4.        

5.           // do your jobs here

6.       }

 

请注意,addobserver的参数填写:其中的object必须是[AVAudioSession sharedInstance],而不是我们通常很多情况下填写的nil,此处若为nil,通知也不会触发。

  

0 0
原创粉丝点击