不管是在Android开发还是iOS开发过程中,有时候我们需要经常根据设备的一些状态或信息进行不同的设置和性能配置,例如横竖屏切换时,电池电量低时,内存不够时,网络切换时等等,我们在这时候需要进行一些友好的提示和保护设备的一些设置。在Android开发中我们可以通过DeviceUtil这个工具类来获取设备网络状态、电池电量等各种状态信息,那么在iOS开发中,我们是否也能获取到设备的各种状态信息呢?答案是肯定的,本文就主要来学习一下在iOS开发过程中如何获取到设备的各种状态信息。

  在iOS中要获取设备的状态信息,主要涉及到三个类:UIDevice、NSbundle和NSlocale。这三个类分别对应不同的信息:

  • UIDevice是设计到设备的状态信息最多最常用的一个类,主要用于获取类函数及状态通知,可以检测手机电量、定位、感应、机型、当前系统版本等等。
  • NSbundle是一个目录,其中包含了程序会使用到的资源,这些资源包含了图像、声音、编译好的代码,通过这些亦可获取一些应用信息。
  • NsLocale可以获取用户的本地化信息,如货币、语言、国家、数字、日期格式、地理位置显示等等。

一 UIDevice

  通过UIDevice可以获取到的信息非常多,UIDevice类展示了一些关键的特定于设备的属性,包括使用的iPhone ,Ipad或iPod Touch型号、设备名称、以及OS名称和版本。他是一种一站式解决方案,用于提取出某些系统详细信息。每个方法都是一个实例方法,他们是使用UIDevice单例通过[UIDevice currentDevice]调用的。

1.1 通过UIDevice获取设备基本状态

  对于通过UIDevice获取到的设备状态信息如下图所示,具体获取方法参见:史上最全的iOS各种设备信息获取总结(iPhone8/iPhone X 已更新)

   

   

1.2 UIDevice中对状态信息的监控

  UIDevice中对设备的方向、电池状态、电量以及距离传感器等信息都能进行获取,有时候我们需要对相应的状态进行监控,以便在状态发生改变时我们采取相应的措施。要对一些状态进行监控,显然最好的办法就是通过通知的方法进行操作,在状态变化时发出通知,然后我们采取对应的方法。下面是UIDevice中提供的通知类型。

//设备方向改变时发送的通知
UIKIT_EXTERN NSString *const UIDeviceOrientationDidChangeNotification;
//电池状态改变时发送的通知
UIKIT_EXTERN NSString *const UIDeviceBatteryStateDidChangeNotification NS_AVAILABLE_IOS(3_0);
//电量改变时发送的通知
UIKIT_EXTERN NSString *const UIDeviceBatteryLevelDidChangeNotification NS_AVAILABLE_IOS(3_0);
//距离传感器状态改变时发送的通知
UIKIT_EXTERN NSString *const UIDeviceProximityStateDidChangeNotification NS_AVAILABLE_IOS(3_0);

其中,设备方向的枚举选项有以下几种:

typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait, // home键在下
UIDeviceOrientationPortraitUpsideDown, // home键在上
UIDeviceOrientationLandscapeLeft, // home键在右
UIDeviceOrientationLandscapeRight, // home键在左
UIDeviceOrientationFaceUp, // 屏幕朝上
UIDeviceOrientationFaceDown // 屏幕朝下
};

电池状态的枚举选项有一下几种:

typedef NS_ENUM(NSInteger, UIDeviceBatteryState) {
UIDeviceBatteryStateUnknown,
UIDeviceBatteryStateUnplugged, // 放电状态
UIDeviceBatteryStateCharging, // 充电未充满状态
UIDeviceBatteryStateFull, // 充电已充满
};

电池电量是一个float类型的值,从0.0 ~ 1.0表示电池电量的百分比:

@property(nonatomic, readonly) float batteryLevel;    //电池电量

距离传感器的状态是用一个BOOL类型的值来表示手机是离用户近还是远:

//A Boolean value indicating whether the proximity sensor is close to the user (YES) or not (NO)
@property(nonatomic, readonly) BOOL proximityState;

当我们需要对某一个信息进行监控时,我们需要进行三步:添加状态通知--> 开启监控开关 --> 完成监控动作(调用方法)

  • 添加状态通知:即将某种状态的监控信息添加到通知中心。

    //添加设备方向的监控通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(change) name:UIDeviceOrientationDidChangeNotification object:nil]; //添加距离状态的监控通知
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(notice) name:UIDeviceProximityStateDidChangeNotification object:nil];
  • 开启监控开关:iOS开发中,UIDevice的每一个状态通知都对应有一个开关来控制是否开启对应的监控和通知,我们需要打开对应状态的开关。
    //打开设备方向监测,这是用方法控制
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; //不需要时可以关闭设备方向监控
    [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; //打开电池状态和电池电量监测开关,不需要时可以关闭
    [UIDevice currentDevice].batteryMonitoringEnabled=YES; //打开手机距离传感器监测开关,不需要时可以关闭
    [UIDevice currentDevice].proximityMonitoringEnabled=YES;

    此外,对于设备方向监控, UIDevice还提供了一个BOOL类型的只读属性来获取当前监控状态:

    //A Boolean value that indicates whether the receiver generates orientation notifications (YES) or not (NO)
    @property(nonatomic, readonly, getter=isGeneratingDeviceOrientationNotifications) BOOL generatesDeviceOrientationNotifications;
  • 完成监控动作:就是所监控的状态发生变化时采取的动作,也就是在第一步添加通知时的 selector:@selector(change) 中方法的完成,这样当监控的状态发生变化是就会自动调用对用的方法执行。
    //设备方向改变时调用该方法
    -(void)change{
    NSLog(@"change");
    } //设备离用户的距离状态发生变化时调用该方法
    -(void)notice{
    if ([UIDevice currentDevice].proximityState) {
    NSLog(@"近距离");
    }else{
    NSLog(@"远距离");
    }
    }

二 设备上安装的App信息

  在开发过程中,有时候我们需要了解设备上安装了那些App,以及是否安装了一些特定的App以方便我们进行开发,最近我们公司的OA项目中就需要将特定类型的OA信息可以转发到微信、QQ上,这时候我们就需要判断设备上是否安装了对应的App,然后进行相关的操作。因此,在这种情况下,获取设备上是否安装了特定的App以及设备上安装了那些App则显得比较重要了。

  那么如何判断我们的iOS设备上是否安装了特定的App呢?有两种方案:

  1. 直接判断是否安装了特定的App
  2. 先获取到iOS设备上安装的所有App的清单,然后判断是否有特定的App

2.1 直接判断iOS设备是否安装了特定的app

  这个方法其实是比较简单的,但是你需要知道该软件的URL Schemes,知道软件的URL Schemes可以使用openUrl来获取ios是否安装了某款软件,比如这样 [[UIApplication sharedApplication] canOpenURL:@"damon://"] ,会返回一个bool值,为true则安装了,否则没有安装。扩展iOS软件之间的调用:IOS的软件之间的调用(URL Schemes)

  方法很简单,但是问题了,我们要如何获取到特定App的URL Schemes呢?下面两个步骤带大家一起学会如何获取:

  1. 获取app的url schemes 的方法 :把相应的 app 的 ipa 安装文件下载下来,把文件 .ipa 的后缀改成 .zip,然后解压,打开 Payload/xxx.app/Info.plist 这个文件,找到 URL types 下的 URL Schemes 下的数组对应的值就是这个 app 的 URL Scheme 了
  2. 简单验证一个 URL Scheme 是否正确的方法:在真机设备(此设备要安装了待验证的 app)里面打开 Safari,然后在地址栏中键入该应用的 URL Scheme,后加 ://,比如 Weico 的,在地址栏中键入 weico:// ,然后点击确定,如果能正常调用出 Weico,即代表这个 URL Scheme 正确可用
  3. 部分URL schemes名单:https://www.zhihu.com/question/19907735,仅做参考,这个不保证正确性

  我们判断某个特定的App是否被安装一般都是用来进行跳转或打开的,如果安装了,我们该如何实现跳转呢?首先,我们需要将检测的UrlScheme添加到白名单即可,添加方法:info.plist 增加LSApplicationQueriesSchemes (array类型),把要检测的app的UrlScheme加进去。

  最后,我们在代码中调用Application 的canopenUrl 的方法判断设备时候有对应的应用 程序,返回YES表示已安装了该app ,代码如下:

if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"IOSDevApp://"]])
{
//说明此设备有安装app
}else{
//说明此设备没有安装app
} 

2.2 获取iOS设备上安装的所有App清单

  要获取iOS设备上安装所有App清单以及一些必要信息,实际上这一个是不允许的,因为涉及到个人隐私问题。但是我们可以通过反射的方法开进行获取。一般的方法是:

 -(void)getAllApp
{
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
NSObject* workspace = [LSApplicationWorkspace_class performSelector:@selector(defaultWorkspace)];
NSArray *allApplications = [workspace performSelector:@selector(allApplications)];//这样就能获取到手机中安装的所有App
NSLog(@"设备上安装的所有app:%@",allApplications);
}

打印出来的结果类似如下形式:

设备上安装的所有app:(
"<LSApplicationProxy: 0x12e563310> com.apple.Passbook <file:///Applications/Passbook.app>",
"<LSApplicationProxy: 0x12e563bb0> com.apple.GameController <file:///Applications/GameController.app>",
)

  从打印结果看出,我们上一步所获取到的allApplications数组中的元素是一个LSApplicationProxy类型的,我们要把这个转换成字符串, 这个字符串中不只包含了App的bundle ID,还包含了安装的路径,因为这个路径不唯一不确定,所以我们判断是否安装了某个App只需判断这个字符串中的bundle ID,所有我们还要对字符串做处理。前提是要知道你要判断的这个app的Bundle ID 是什么。

//解析数据,获取每一个app信息总的
Class LSApplicationProxy_class = object_getClass(@"LSApplicationProxy");
for (LSApplicationProxy_class in appList)
{
//这里可以查看一些信息
NSString *bundleID = [LSApplicationProxy_class performSelector:@selector(applicationIdentifier)];
NSString *version = [LSApplicationProxy_class performSelector:@selector(bundleVersion)];
NSString *shortVersionString = [LSApplicationProxy_class performSelector:@selector(shortVersionString)];
NSLog(@"bundleID:%@\n version: %@\n ,shortVersionString:%@\n", bundleID,version,shortVersionString);
}

从所有安装App信息中判断是否安装了特定App的方法:

-(void)isInstallLDApp:(NSArray *)allAPP
{
NSInteger zlConnt = ;
for (NSString *appStr in allAPP) {
  NSString *app = [NSString stringWithFormat:@"%@",appStr];//转换成字符串
  NSRange range = [app rangeOfString:@"LdWBrowserIPhone"];//是否包含这个bundle ID
if (range.length > ){
  zlConnt ++;
}
}
if (zlConnt >= ) {
  NSLog(@"已安装");
}else{
NSLog(@"没有安装");
}
}

2.3 总结

  • 方法一的优点:效率高,代码量小 ,但前提是要先知道要判断的app 的UrlSchemes
  • 方法二的优点:完美解决iOS9的canopenurl 白名单的限制;

缺点: 遍历的过程中可能会消耗性能, App Store审核可能会被拒,前提是要知道你要判断的这个app的Bundle ID 是什么

三 NSbundle和NSlocale

  参考自:ios开发之UIDevice使用总结

  bundle是一个目录,其中包含了程序会使用到的资源. 这些资源包含了如图像,声音,编译好的代码,nib文件(用户也会把bundle称为plug-in). 对应bundle,cocoa提供了类NSBundle.一个应用程序看上去和其他文件没有什么区别. 但是实际上它是一个包含了nib文件,编译代码,以及其他资源的目录. 我们把这个目录叫做程序的main bundle。通过这个路径可以获取到应用的信息,例如应用名、版本号等。通过NSBundle可以获得这几个信息:

//app应用相关信息的获取
NSDictionary *dicInfo = [[NSBundle mainBundle] infoDictionary];
// CFShow(dicInfo);
NSString *strAppName = [dicInfo objectForKey:@"CFBundleDisplayName"];
NSLog(@"App应用名称:%@", strAppName); NSString *strAppVersion = [dicInfo objectForKey:@"CFBundleShortVersionString"];
NSLog(@"App应用版本:%@", strAppVersion); NSString *strAppBuild = [dicInfo objectForKey:@"CFBundleVersion"];
NSLog(@"App应用Build版本:%@", strAppBuild);

  NSLocale可以获取用户的本地化信息设置,例如货币类型,国家,语言,数字,日期格式的格式化,提供正确的地理位置显示等等。下面的代码获取机器当前语言和国家代码。通过NSLocale可以这样使用:

NSArray *languageArray = [NSLocale preferredLanguages];
NSString *language = [languageArray objectAtIndex:];
NSLog(@"语言:%@", language);//en NSLocale *locale = [NSLocale currentLocale];
NSString *country = [locale localeIdentifier];
NSLog(@"国家:%@", country); //en_US

iOS学习——获取iOS设备的各种信息的更多相关文章

  1. IOS学习之IOS沙盒(sandbox)机制和文件操作

    IOS学习之IOS沙盒(sandbox)机制和文件操作(一) 1.IOS沙盒机制 IOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都 ...

  2. IOS学习:ios中的数据持久化初级(文件、xml、json、sqlite、CoreData)

    IOS学习:ios中的数据持久化初级(文件.xml.json.sqlite.CoreData) 分类: ios开发学习2013-05-30 10:03 2316人阅读 评论(2) 收藏 举报 iOSX ...

  3. iOS学习之iOS沙盒(sandbox)机制和文件操作1

    iOS学习之iOS沙盒(sandbox)机制和文件操作 接上篇 iOS学习之iOS沙盒(sandbox)机制和文件操作(一) 我们看看如何获取应用程序沙盒目录.包括真机的沙盒的目录. 1.获取程序的H ...

  4. html5+ 获取当前设备的加速度信息

    getCurrentAcceleration 获取当前设备的加速度信息 void plus.accelerometer.getCurrentAcceleration( successCB, error ...

  5. linux系统从pci.ids文件获取硬件设备详细厂商信息

    机器采样: [root@ht24 hwdata]# cat /etc/redhat-release ; uname -r CentOS Linux release 7.9.2009 (Core) 3. ...

  6. iOS学习——获取当前最顶层的ViewController

    在iOS开发过程中,我们经常性会需要获取当前页面的ViewController,然后利用ViewController进行一些操作,例如在最顶层的ViewController上展示一个UIAlertCo ...

  7. iOS: 如何获取ios设备的当前IP地址

    有的时候,我们项目上线后,需要根据ip地址去统计不同地区的用户情况,此时IP地址的收取显得尤其重要,一般情况下,在用户登录时去获取用户的ip是准确的,当然实时追踪ip的变化而统计是更安全可靠的. ip ...

  8. iOS下获取用户当前位置的信息

    #import <MapKit/MKMapView.h> @interface ViewController (){ CLLocationManager *_currentLoaction ...

  9. iOS开发——获取本设备IP

    不说废话,直接上代码. #import <ifaddrs.h> #import <arpa/inet.h> - (NSString *)getIPAddress { NSStr ...

随机推荐

  1. 大白话Vue源码系列(03):生成AST

    阅读目录 AST 节点定义 标签的正则匹配 解析用到的工具方法 解析开始标签 解析结束标签 解析文本 解析整块 HTML 模板 未提及的细节 本篇探讨 Vue 根据 html 模板片段构建出 AST ...

  2. 数据结构(C实现)------- 最小生成树之Prim算法

    [本文是自己学习所做笔记.欢迎转载.但请注明出处:http://blog.csdn.net/jesson20121020] 算法描写叙述 假设连通图是一个网,则称该网中全部生成树中权值总和最小的生成树 ...

  3. 负载均衡之基于L7负载

    L7负载平衡 还有一种较为经常使用的负载平衡解决方式则是L7负载平衡.顾名思义,其主要通过OSI模型中的第七层应用层中的数据决定怎样分发负载. 在执行时.L7负载平衡server上的操作系统会将接收到 ...

  4. 在线安装eclipse中html/jsp/xml editor插件(很可靠)

    之前有一篇文章也是安装eclipse中的web开发插件 ,可是经过非常多人使用,那种方法.不是全部人使用都能够. 接下来,找到一种很管用的方法.就是在线安装. 废话不多说,这样的方法绝对能够成功安装. ...

  5. One-Based Arithmetic

    One-Based Arithmetic time limit per test 0.5 seconds memory limit per test 256 megabytes input stand ...

  6. 如何通过PowerShell获取Office 365 TenantID

    作者:陈希章 发表于2017年5月31日 安装Azure Powershell 模块 Installing the Azure PowerShell Service Management module ...

  7. redis中与key相关的命令

    1.简单描述 redis本质上是一个key-value db,value可以有多种类型(string.hash.set.sorted set.list等),本章节不讲这些类型的命令,这里是讲跟key相 ...

  8. Eclipse Maven构建WebApp项目资源目录显示不全的原因与解决方式

    一.问题展示 1.Eclipse在使用Maven构建WebApp项目的时候,首先Maven的安装和配置都没有问题的,但是构建项目之后,Maven项目要求的几个必须要有的资源目录显示不了: 问题如下图: ...

  9. java.lang.NoSuchMethodError: com.itextpdf.text.pdf.PdfDiv.setKeepTogether(Z)V

    用com.itextpdf.text.Document打印pdf报错 时间:2017-06-22 12:23:39,594 - 级别:[ERROR] - 消息: [other] Servlet.ser ...

  10. CRL快速开发框架升级到4.52,谈谈开发过程中的优化

    CRL4.5版本已经稳定使用于目前的几个中型项目中,在实际使用中,也发现了不少问题,这些问题都在4.52中提交 CRL具体功能和使用请浏览 CRL快速开发框架系列教程 由于现在项目是一套业务系统,查询 ...