2017-03-21 18:19:27 studying_ios 阅读数 4101
  • iOS进阶开发

    进阶课程涵盖目前iOS开发需要提升和深入研究的基础知识.通过原理讲解,深入理解底层机制.课程答疑讲师QQ:471926977

    1737 人正在学习 去看看 李文瀚

最近做一个需求:后端需要统计使用我们APP产品的用户手机的各种信息,这些信息包括:设备品牌、设备型号、设备分辨率、操作系统、运营商、APP版本号、设备ID(UUID)、地址位置。这些信息其实获取也都不是很难,简单记录一下:

//首先获取当前设备对象
    UIDevice *device = [UIDevice currentDevice];

    /* 系统名 */
    NSString *systemName = [device systemName];

    /* 系统版本号 */
    NSString *phoneVersion = [device systemVersion];

    /* 设备品牌 */
    NSString *brand = [device model];

    /* 设备型号 */  iphoneType方法在后面实现
    NSString *model = [self iphoneType];

    /* 分辨率 */ 
    CGRect rect = [UIScreen mainScreen].bounds;
    CGSize size = rect.size;
    CGFloat scale = [UIScreen mainScreen].scale;
    CGFloat width = size.width*scale;
    CGFloat height = size.height*scale;

    /* 运营商 */
首先需要引入以下两个系统类:
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreTelephony/CTCarrier.h>

    CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init];
    CTCarrier *carrier = [info subscriberCellularProvider];
    //当前手机所属运营商名称
    NSString *mobileCarrier;
    //先判断有没有SIM卡,如果没有则不获取本机运营商
    if (!carrier.isoCountryCode) {
        mobileCarrier = @"无运营商";
    }else{
        mobileCarrier = [carrier carrierName];
    }

    /* app当前版本号 */
    NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
    NSString *currentVersion = infoDict[@"CFBundleShortVersionString"];

    /* 设备ID */
    NSUUID *uuid = device.identifierForVendor;
    NSString *devideID = uuid.UUIDString;

    /* 地理位置 */
    [self Collocaction];

获取设备型号的方法:

- (NSString *)iphoneType {

    //需要导入头文件:#import <sys/utsname.h>

    struct utsname systemInfo;

    uname(&systemInfo);

    NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding];

    if ([platform isEqualToString:@"iPhone1,1"]) return @"iPhone 2G";

    if ([platform isEqualToString:@"iPhone1,2"]) return @"iPhone 3G";

    if ([platform isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS";

    if ([platform isEqualToString:@"iPhone3,1"]) return @"iPhone 4";

    if ([platform isEqualToString:@"iPhone3,2"]) return @"iPhone 4";

    if ([platform isEqualToString:@"iPhone3,3"]) return @"iPhone 4";

    if ([platform isEqualToString:@"iPhone4,1"]) return @"iPhone 4S";

    if ([platform isEqualToString:@"iPhone5,1"]) return @"iPhone 5";

    if ([platform isEqualToString:@"iPhone5,2"]) return @"iPhone 5";

    if ([platform isEqualToString:@"iPhone5,3"]) return @"iPhone 5c";

    if ([platform isEqualToString:@"iPhone5,4"]) return @"iPhone 5c";

    if ([platform isEqualToString:@"iPhone6,1"]) return @"iPhone 5s";

    if ([platform isEqualToString:@"iPhone6,2"]) return @"iPhone 5s";

    if ([platform isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus";

    if ([platform isEqualToString:@"iPhone7,2"]) return @"iPhone 6";

    if ([platform isEqualToString:@"iPhone8,1"]) return @"iPhone 6s";

    if ([platform isEqualToString:@"iPhone8,2"]) return @"iPhone 6s Plus";

    if ([platform isEqualToString:@"iPhone8,4"]) return @"iPhone SE";

    if ([platform isEqualToString:@"iPhone9,1"]) return @"iPhone 7";

    if ([platform isEqualToString:@"iPhone9,2"]) return @"iPhone 7 Plus";
    return platform;
}

定位相关的实现:使用CLLocationManager和CLLocation两个类

-(void)Collocaction{

    self.locationManager = [[CLLocationManager alloc] init];

    [self.locationManager  requestAlwaysAuthorization];//请求授权
    if ([CLLocationManager locationServicesEnabled]) {
        self.locationManager.delegate = self;
        self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
        self.locationManager.distanceFilter = 200.0f;
        [self.locationManager startUpdatingLocation];
    }
    else {
        NSLog(@"请开启定位功能!");
    }
}
//定位代理方法
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation

           fromLocation:(CLLocation *)oldLocation {

    // 获取当前所在的城市名
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    //根据经纬度反向地理编译出地址信息
    [geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *array, NSError *error)
     {
         if (array.count > 0)
         {
             CLPlacemark *placemark = [array objectAtIndex:0];
             //获取城市
             NSString *city = placemark.locality;
             if (!city) {
                 //四大直辖市的城市信息无法通过locality获得,只能通过获取省份的方法来获得(如果city为空,则可知为直辖市)
                 city = placemark.administrativeArea;
             }
             //详细地址
             NSString *location = placemark.name;
             //拼接成最终的位置
             NSString *myLocation = [NSString stringWithFormat:@"%@%@",city,location];
         }
         else if (error == nil && [array count] == 0)
         {
             NSLog(@"No results were returned.");
         }
         else if (error != nil)
         {
             NSLog(@"An error occurred = %@", error);
         }
     }];

    //停止定位
    [manager stopUpdatingLocation];
}
// 定位失误时调用
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog(@"error:%@",error);
}
2013-06-21 15:43:04 teng_ontheway 阅读数 1824
  • iOS进阶开发

    进阶课程涵盖目前iOS开发需要提升和深入研究的基础知识.通过原理讲解,深入理解底层机制.课程答疑讲师QQ:471926977

    1737 人正在学习 去看看 李文瀚
在IOS上存在retain屏,经常需要在一些时刻用到高清图,有些时候也要到普通图。 
在网络条件很爽的情况下,这当然不在话下。如果咱是iphone用户,又正好用的是移动卡。 
如果还用的高清图的话是不是灰常的杯具,显然是一定的。 
从目前的情况来看,只有移动的gprs的卡速度慢的像牛一样,这样我们就需要权衡在一些场合牺牲点质量 
换取速度。 

那么我们就得必须知道当前网络是神马运营商。给个变通的解决方案。

- (BOOL)checkChinaMobile
{
    BOOL ret = NO;
    CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init];
    CTCarrier *carrier = [info subscriberCellularProvider];
    if (carrier == nil) {
        [info release];
        return NO;
    }

    NSString *code = [carrier mobileNetworkCode];
    if (code == nil) {
        [info release];
        return NO;
    }

    if ([code isEqualToString:@"00"] || [code isEqualToString:@"02"] || [code isEqualToString:@"07"]) {
        ret = YES;
    }
    [info release];

    return ret;
}



网络在00—02—07三种情况时是移动网络。具体参考下面的数据 
China – CN

详细数据请参考: http://en.wikipedia.org/wiki/Mobile_Network_Code
转自iloss博客 http://www.iloss.me/2012/07/21/ios如何判断当前网络的运营商/

同类文章参考点击打开链接
2014-12-03 10:57:51 u012476249 阅读数 2649
  • iOS进阶开发

    进阶课程涵盖目前iOS开发需要提升和深入研究的基础知识.通过原理讲解,深入理解底层机制.课程答疑讲师QQ:471926977

    1737 人正在学习 去看看 李文瀚

这个问题坑了很久了,终于搞定了 —。—|||

如果使用CoreTelephony.framework 框架,获取的仅仅是Sim卡的运营商(而且还不成功!carrier.name属性为Carrier,坑死人了!)

那么思路稍微转一下,当手机漫游的时候,会接入当地的运营商,在手机Status Bar上会显示出来,那么只要获得Status Bar上显示的名字即可获得漫游手机接入网络的运营商了。

(1)进入Rumtime模式

#import <objc/message.h>

 

(2)进入实现代码:

要知道最终获取到状态栏上的运营商名称要经过一层层的提取,下面就开始一层层分析

1. 获得标题栏并遍历其中的所有元素

    //状态栏是由当前app控制的,首先获取当前app

        UIApplication *app = [UIApplicationsharedApplication];

           id statusBar = [app valueForKeyPath:@"statusBar"];

        // 遍历状态栏的所有成员

       unsigned int outCount =0;

       Ivar *ivars = class_copyIvarList([statusBarclass], &outCount);

       for (int i =0; i < outCount; i++) {

           Ivar ivar = ivars[i];

           printf("%s\n",ivar_getName(ivar));

        }


打印出的元素有:

_styleDelegate

_statusBarWindow

_statusBarServer

_showsForeground

_backgroundView

_foregroundView

_doubleHeightLabel

_currentDoubleHeightText

_currentRawData

_interruptedAnimationCompositeViews

_newStyleBackgroundView

_newStyleForegroundView

_slidingStatusBar

_requestedStyle

_styleOverrides

_style

_orientation

_hidden

_suppressesHiddenSideEffects

_foreground

_registered

_styleRequestedWhileHidden

_waitingOnCallbackAfterChangingStyleOverridesLocally

_suppressGlow

_translucentBackgroundAlpha

_showOnlyCenterItems

_localDataOverrides

_tintColor

_lastUsedTintColor

_nextTintTransition


2. 进入foregroundView元素并遍历其所有子元素

    NSArray *children = [[[appvalueForKeyPath:@"statusBar"]valueForKeyPath:@"foregroundView"]subviews];

   for (id childin children) {

       NSLog(@"%@", [childclass]);

    }

打印结果如下:

UIStatusBarSignalStrengthItemView

UIStatusBarServiceItemView

UIStatusBarDataNetworkItemView

UIStatusBarBatteryItemView

UIStatusBarBatteryPercentItemView

UIStatusBarTimeItemView


3. 进入UIStatusBarServiceItemView元素并遍历其所有子元素

   NSArray *children = [[[appvalueForKeyPath:@"statusBar"]valueForKeyPath:@"foregroundView"]subviews];

   for (id childin children) {

        if ([childisKindOfClass:NSClassFromString(@"UIStatusBarServiceItemView")]) {

           unsigned int outCount =0;

           Ivar *ivars = class_copyIvarList([childclass], &outCount);

           for (int i =0; i < outCount; i++) {

               Ivar ivar = ivars[i];

               printf("%s\n",ivar_getName(ivar));

            }

        }

    }


打印结果如下:

_pathToServiceImages

_serviceString

_crossfadeString

_crossfadeStep

_maxWidth

_serviceWidth

_crossfadeWidth

_contentType

_loopingNecessaryForString

_usingStringForStyle

_loopNowIfNecessary

_letterSpacing


4. 通过serviceString获取运营商名称

    NSArray *children = [[[app valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];

    for (id child in children) {

        if ([child isKindOfClass:NSClassFromString(@"UIStatusBarServiceItemView")]) {

            // 遍历当前状态栏的所有属性,找到关于状态栏的

            id type = [child valueForKeyPath:@"serviceString"];

            NSLog(@"carrier is %@", type);

            break;

        }

    }

打印结果:

carrier is 中国联通


总结一下,获取标题栏上的运营商的名称主要过程为:

statusBar ->  foregroundView -> UIStatusBarServiceItemView ->  serviceString -> 运营商名字


最后贴一下代码供大家参考

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    // 状态栏是由当前app控制的,首先获取当前app
    UIApplication *app = [UIApplication sharedApplication];
    NSArray *children = [[[app valueForKeyPath:@"statusBar"] valueForKeyPath:@"foregroundView"] subviews];
    for (id child in children) {
        if ([child isKindOfClass:NSClassFromString(@"UIStatusBarServiceItemView")]) {
            id type = [child valueForKeyPath:@"serviceString"];
            NSLog(@"carrier is %@", type);
            break;
        }
    }
    
    return YES;
}





2016-09-19 18:50:03 qq_21649645 阅读数 239
  • iOS进阶开发

    进阶课程涵盖目前iOS开发需要提升和深入研究的基础知识.通过原理讲解,深入理解底层机制.课程答疑讲师QQ:471926977

    1737 人正在学习 去看看 李文瀚

CoreTelephony是苹果提供的用来访问用户的移动服务提供商的信息,比如它的唯一标识符,以及是否允许VoIP通话。获取当前通过的id以及状态。

CoreTelephony在iOS7之前是私有API,在iOS7之后苹果公开了CoreTelephony。 

https://developer.apple.com/reference/coretelephony


1.可以用CoreTelephony获取手机运营商的信息。

- (void)getcarrierName

{

    CTTelephonyNetworkInfo *telephonyInfo = [[CTTelephonyNetworkInfo alloc] init];

    CTCarrier *carrier = [telephonyInfo subscriberCellularProvider];

    NSString *currentCountry = [carrier carrierName];   // 运营商名字

    NSLog(@"[carrier isoCountryCode]==%@,[carrier allowsVOIP]=%d,[carrier mobileCountryCode=%@,[carrier mobileCountryCode]=%@",[carrier isoCountryCode],[carrier allowsVOIP],[carrier mobileCountryCode],[carrier mobileNetworkCode]);

}


2.可以用CoreTelephony监控通话信息。

CTCallCenter *center = [[CTCallCenter alloc] init];

center.callEventHandler = ^(CTCall *call) {

    NSString *callState = call.callState;

    NSString *callID = call.callID;

};


3.号外:获取当前使用网络的运营商的信息。

- (void)networkMobile

{

    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

    manager.responseSerializer = [AFJSONResponseSerializer serializer];

    manager.requestSerializer = [AFJSONRequestSerializer serializer];

    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", nil];

    

    [manager GET:@"http://g3.letv.cn/recommend?format=1" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

        if (responseObject && [responseObject isKindOfClass:[NSDictionary class]]) {

            NSLog(@"%@ >> %@", responseObject, responseObject[@"desc"]);

        }

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        

    }];

}




2017-01-12 15:35:24 o190847959 阅读数 648
  • iOS进阶开发

    进阶课程涵盖目前iOS开发需要提升和深入研究的基础知识.通过原理讲解,深入理解底层机制.课程答疑讲师QQ:471926977

    1737 人正在学习 去看看 李文瀚

对于特殊机型的问题,经常会遇到对当前的APP所在手机做运营商(华为,三星,小米,魅族等)和机型的判断,主要是通过如下两个系统的方法判断。更多信息也是通过类似的方式获取,此处只是给个思路,网上的参考很多,但是有些解释容易误解。
下面的两个函数分别是用来获取当前手机的运行商和型号。

private String getCurrentOS(){
        return android.os.Build.BRAND;
    }

private String getCurrentModel(){
    return android.os.Build.MODEL;
}
没有更多推荐了,返回首页