获取线上应用信息有两个接口可以使用:
- https://itunes.apple.com/lookup?id={appid}
- https://itunes.apple.com/cn/lookup?id={appid}
有帖子说在国内建议使用第二个链接,在国外建议使用第一个链接,就目前使用情况没有看到两个接口有太大的区别,不放心的话可以两个都调用一下.
坑点
虽然iOS的应用不建议用户在应用内部进行应用更新的提示,对于选择性更新来说,用户是否更新并没有太大的影响,但是在很多情况下(例如某个新功能只有在新版本上才有,或者紧急bug的修复等)我们还是不得不在应用内部实现强制更新功能来让尽可能多的活跃用户使用到最新的应用版本.这时候就需要使用接口来获取线上的应用信息,来判断是否需要进行更新提示操作,一般的做法有两种思路:
- 在自己的后台手动设置更新配置:当应用发布之后,手动修改后台的配置,让应用获取到最新的应用信息,通过与本地版本号做比对,来判断是否提示用户进行更细;
- 直接从iTunes的后台接口获取线上应用信息:在应用中通过接口来获取线上应用的最新信息,判断是是否提示用户进行更新;
对于第一种思路来讲,有时候会由于设备所处的地域不同,网络状态有差异等情况导致用户所在的地方访问app store时,发现线上应用版本并没有更新还是停留在上一个版本.这就比较尴尬了,应用要求我进行更新,可是我在app store却没有发现新的版本回到应用之后依旧在提示需要更新,从而造成非常糟糕的体验.而且比较有时候容易被审核认定为,在审核期间隐藏应用功能,所以不太建议使用.
对于第二种情况来讲,我们可以获取到设备当前环境下的最新线上信息,相对来讲会比第一种情况具备更加及时的真实信息,也更具有针对性,但是这里有一个坑点.对于网络请求来讲,或许你会觉得在服务器支持的情况下,使用GET或者POST方式发起请求对于请求本身来讲并没有什么影响,但是不幸的是,这个接口真的影响.如果你使用了GET方式进行数据请求,就会发现即使新版本的线上应用已经发很久,接口获取到的数据依然是上一个版本的应用信息,这种情况有时候可以甚至持续数周.解决方案就是使用POST来发起请求,最新的数据就会比较及时的反馈回来.
所以获取线上应用信息不要使用GET!
不要使用GET!
不要使用GET!
NSString *appId = @"your appid";
NSString *url = @"https://itunes.apple.com/cn/lookup";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
request.HTTPMethod = @"POST";
request.HTTPBody = [[NSString stringWithFormat:@"id=%@", appId] dataUsingEncoding:NSUTF8StringEncoding];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSError *responseError = nil;
id result = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingMutableContainers) error:&responseError];
if(error) {
NSLog(@"responseError == %@", responseError);
} else {
NSLog(@"result == %@", result);
}
}];
[task resume];
获取到的数据大概这个样子:
result == {
resultCount = 1;
results = (
{
advisories = (
);
appletvScreenshotUrls = (
);
artistId = xxxxxxxxxx;
artistName = "";
artistViewUrl = "";
artworkUrl100 = "";
artworkUrl512 = "";
artworkUrl60 = "";
bundleId = "";
contentAdvisoryRating = "4+";
currency = CNY;
currentVersionReleaseDate = "2019-08-27T14:54:16Z";
description = "";
features = (
iosUniversal
);
fileSizeBytes = 18037760;
formattedPrice = "";
genreIds = (
6001
);
genres = (
"\U5929\U6c14"
);
ipadScreenshotUrls = (
"",
"",
"",
"",
""
);
isGameCenterEnabled = 0;
isVppDeviceBasedLicensingEnabled = 1;
kind = software;
languageCodesISO2A = (
EN
);
minimumOsVersion = "8.0";
price = 0;
primaryGenreId = 6001;
primaryGenreName = Weather;
releaseDate = "2019-03-27T19:54:28Z";
releaseNotes = "";
screenshotUrls = (
"",
"",
"",
""
);
sellerName = "";
supportedDevices = (
"iPad2Wifi-iPad2Wifi",
"iPad23G-iPad23G",
"iPhone4S-iPhone4S",
"iPadThirdGen-iPadThirdGen",
"iPadThirdGen4G-iPadThirdGen4G",
"iPhone5-iPhone5",
"iPodTouchFifthGen-iPodTouchFifthGen",
"iPadFourthGen-iPadFourthGen",
"iPadFourthGen4G-iPadFourthGen4G",
"iPadMini-iPadMini",
"iPadMini4G-iPadMini4G",
"iPhone5c-iPhone5c",
"iPhone5s-iPhone5s",
"iPadAir-iPadAir",
"iPadAirCellular-iPadAirCellular",
"iPadMiniRetina-iPadMiniRetina",
"iPadMiniRetinaCellular-iPadMiniRetinaCellular",
"iPhone6-iPhone6",
"iPhone6Plus-iPhone6Plus",
"iPadAir2-iPadAir2",
"iPadAir2Cellular-iPadAir2Cellular",
"iPadMini3-iPadMini3",
"iPadMini3Cellular-iPadMini3Cellular",
"iPodTouchSixthGen-iPodTouchSixthGen",
"iPhone6s-iPhone6s",
"iPhone6sPlus-iPhone6sPlus",
"iPadMini4-iPadMini4",
"iPadMini4Cellular-iPadMini4Cellular",
"iPadPro-iPadPro",
"iPadProCellular-iPadProCellular",
"iPadPro97-iPadPro97",
"iPadPro97Cellular-iPadPro97Cellular",
"iPhoneSE-iPhoneSE",
"iPhone7-iPhone7",
"iPhone7Plus-iPhone7Plus",
"iPad611-iPad611",
"iPad612-iPad612",
"iPad71-iPad71",
"iPad72-iPad72",
"iPad73-iPad73",
"iPad74-iPad74",
"iPhone8-iPhone8",
"iPhone8Plus-iPhone8Plus",
"iPhoneX-iPhoneX",
"iPad75-iPad75",
"iPad76-iPad76",
"iPhoneXS-iPhoneXS",
"iPhoneXSMax-iPhoneXSMax",
"iPhoneXR-iPhoneXR",
"iPad812-iPad812",
"iPad834-iPad834",
"iPad856-iPad856",
"iPad878-iPad878",
"Watch4-Watch4",
"iPadMini5-iPadMini5",
"iPadMini5Cellular-iPadMini5Cellular",
"iPadAir3-iPadAir3",
"iPadAir3Cellular-iPadAir3Cellular",
"iPodTouchSeventhGen-iPodTouchSeventhGen",
"iPhone11-iPhone11",
"iPhone11Pro-iPhone11Pro",
"Watch5-Watch5",
"iPadSeventhGen-iPadSeventhGen",
"iPadSeventhGenCellular-iPadSeventhGenCellular",
"iPhone11ProMax-iPhone11ProMax"
);
trackCensoredName = "";
trackContentRating = "4+";
trackId = xxxxxxxxxx;
trackName = "";
trackViewUrl = "";
version = "1.4.0";
wrapperType = software;
}
);
}
如何区分应用状态
- 区分是否审核状态
上边我们提到在使用自己的接口判断应用是否在审核中时,有可能会被认定为刻意在审核期间隐藏功能.那么在获取到线上应用信息之后如何判断应用是在审核中还是审核之后呢?
这个问题就比简单了,通过线上应用的版本号来跟当前应用作比较,如果线上应用的版本号大于当前应用的版本号,那应用就处于审核状态.
NSString *versionOnline = [(NSArray *)result[@"results"] firstObject][@"version"] ; NSString *versionLocal = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]; NSComparisonResult compareResult = [versionLocal compare:versionOnline options:(NSNumericSearch)]; if (compareResult == NSOrderedDescending) { NSLog(@"审核中"); } else { NSLog(@"非审核中"); }
- 如何是否强制更新
这里提供一种简单的思路:正常的更新版本号使用3位分割,例如1.2.0;当需要强更时可以使用两位版本号,例如1.2.这样在需要更新时就可以根据版本号的尾数来判断是否需要强制更新.
NSString *versionOnline = [(NSArray *)result[@"results"] firstObject][@"version"] ;
NSString *versionLocal = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
NSComparisonResult compareResult = [versionLocal compare:versionOnline options:(NSNumericSearch)];
if (compareResult == NSOrderedDescending) {
NSLog(@"审核中");
} else {
if (compareResult == NSOrderedAscending) {
if ([versionOnline componentsSeparatedByString:@"."].count == 2) {
NSLog(@"需要强制更新");
} else {
NSLog(@"需要选择更新");
}
}
NSLog(@"非审核中");
}