我可以强制iPhone用户升级应用程序吗?

时间:2010-02-08 12:14:27

标签: iphone itunesconnect

一旦iTunes Store中有我的应用程序的新版本,是否可以强制用户升级?

我目前正在开发一个应用程序。但是,我想在上传新版本时强制升级,因为升级会有更多功能,我想放弃以前的版本。这是默认使用iPhone的可能吗?还是我必须编写自己的实现来检查当前版本并将其与商店进行比较?

14 个答案:

答案 0 :(得分:36)

我通过从itunes webservice获取版本并与当前版本进行比较来完成此功能..以下是我的代码

        NSString *version = @"";
        NSURL *url = [NSURL URLWithString:@"http://itunes.apple.com/lookup?id=<Your app ID>"];
        versionRequest = [ASIFormDataRequest requestWithURL:url];
        [versionRequest setRequestMethod:@"GET"];
        [versionRequest setDelegate:self];
        [versionRequest setTimeOutSeconds:150];
        [versionRequest addRequestHeader:@"Content-Type" value:@"application/json"]; 
        [versionRequest startSynchronous];

        //Response string of our REST call
        NSString* jsonResponseString = [versionRequest responseString];

        NSDictionary *loginAuthenticationResponse = [jsonResponseString objectFromJSONString];

        NSArray *configData = [loginAuthenticationResponse valueForKey:@"results"];

        for (id config in configData) 
        {
            version = [config valueForKey:@"version"];
        }
   //Check your version with the version in app store
        if (![version isEqualToString:[itsUserDefaults objectForKey:@"version"]]) 
        {
            ProAlertView *createUserResponseAlert = [[ProAlertView alloc] initWithTitle:@"New Version!!" message: @"A new version of app is available to download" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles: @"Download", nil];
        [createUserResponseAlert show]; 
        [createUserResponseAlert release];
        }

将app id放入itunes链接,请参阅下面的代码。

- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    // the user clicked one of the OK/Cancel buttons
    if (buttonIndex == 1)
    {
        NSString *iTunesLink = @"itms-apps://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftwareUpdate?id=<appid>&mt=8";
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:iTunesLink]];
    }
}

注意:您需要JSONKit框架工作和ASIHttp框架工作才能进行Web服务调用..

答案 1 :(得分:21)

您可以检测应用是否需要更新,然后采取一些自定义操作,例如提醒用户更新可用。以下是检测到更新可用的代码段。

-(BOOL) needsUpdate{
    NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
    NSString* appID = infoDictionary[@"CFBundleIdentifier"];
    NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@", appID]];
    NSData* data = [NSData dataWithContentsOfURL:url];
    NSDictionary* lookup = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

    if ([lookup[@"resultCount"] integerValue] == 1){
        NSString* appStoreVersion = lookup[@"results"][0][@"version"];
        NSString* currentVersion = infoDictionary[@"CFBundleShortVersionString"];
        if (![appStoreVersion isEqualToString:currentVersion]){
            NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
            return YES;
        }
    }
    return NO;
}

答案 2 :(得分:18)

如果您必须这样做,您可以启动App Store,以便您的用户可以从那里获得最新版本。我建议先选择这个,或至少先展示对话。

// iTunesLink should be your applications link
NSString *iTunesLink = @"http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=284417350&mt=8";


[[UIApplication sharedApplication] openURL:[NSURL URLWithString:iTunesLink]];

答案 3 :(得分:11)

此问题最初发布于7年前,虽然部分答案仍然相关,但这是一种更新的方法。

我建议使用兼容Swift 3的https://github.com/ArtSabintsev/Siren,可以与Cocoapods或Carthage一起安装。

CocoaPods,Swift 3支持:

from selenium import webdriver from selenium.webdriver.common.desired_capabilities import DesiredCapabilities from selenium.common.exceptions import TimeoutException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC user_agent = ( "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36" ) dcap = dict(DesiredCapabilities.PHANTOMJS) dcap["phantomjs.page.settings.userAgent"] = user_agent driver = webdriver.PhantomJS(desired_capabilities=dcap, executable_path=r'/bin/phantomjs') driver.get('http://web.whatsapp.com') timeout = 30 try: element_present = EC.presence_of_element_located((By.Class, 'qrcode')) WebDriverWait(driver, timeout).until(element_present) except TimeoutException: print "Timed out waiting for page to load"

迦太基:

pod 'Siren'

答案 4 :(得分:5)

系统处理应用程序更新的唯一方法是提示用户在标准AppStore应用程序中可以使用更新 此外,独立应用程序不知道可用的更新,因此您需要实现您的Web服务,应用程序可以检查当前版本是否有效。
而且我不确定这是否符合Apple关于应用程序的规则,例如(无法找到证据链接)您无法上传应用程序的试用版本。

*编辑* 这个答案不再适用。查看当前事实的其他赞成答案。

答案 5 :(得分:5)

强制升级的系统应该是每个依赖于该应用程序外部内容的应用程序的一部分。苹果和谷歌都声称,如果一个应用程序使用外部的东西,那么外部API应该永远存在,永远不会改变,等等,但这是不切实际的。如果是这种情况,如果应用所依赖的服务可以改变,那么必须是应用程序检查的一种方式,看它是否应该限制功能并提示用户获取最新版本或者事情会神秘地失败。

这可能也应该是苹果和谷歌提供的东西,但它们并不是因此,除了少数游戏之外的每个应用程序都需要构建它,所以... ...

我已经开始了一个基于rails的开源(Apache 2.0)项目来创建这个问题的解决方案。它被称为Application- [Ctrl],它正在进行中,但欢迎您使用它,我欢迎任何形式的贡献。如果我可以在业余时间启动并运行,我会向所有应用程序开发人员提供一些非常合理的免费服务,当然每家公司都能够自行部署它。

这是在GitHub:https://github.com/SlalomDigital/ApplicationCtrl

贡献并帮助我解决这个问题!

答案 6 :(得分:4)

没有自动化的方法,您必须手动编写内容。

答案 7 :(得分:4)

您的商家/设计方案绝不应包含“强制用户”这一短语。当你让他们做某事时,人们会生气。想象一下匆忙的用户一天早上打开你漂亮的小应用程序只是为了发现你在他可以使用应用程序满足他的需求之前强迫他升级。想象一下,他在野外不得不使用Edge进行下载。他不会幸福。

如果你按照这个计划进行足够长的时间,你的升级之一将不可避免地引入一个明显的错误。如果你强迫用户使用有缺陷的版本,他们会反叛。

每当我看到用于描述新版本软件的“更多功能”时,我就会受到经验的限制,因为这不可避免地意味着功能臃肿。设计师倾向于继续在应用程序上移植越来越多的功能,直到一个应用程序完成所有操作这在像iPhone这样的平台上尤其危险,在这个平台上,一个应用程序可以做很多事情,迅速淹没界面和应用程序的响应能力。

Edit01:我在此处的评论How to Update an Application After Users Pay For Upgrade也可能与您的计划相关。如果你的升级设计将Apple从收入循环中剔除,那么它就是一个非首发。

<强>更新

根据以下评论澄清:是的,有时您必须要求用户升级。但是,这与 设计 应用 从一开始 大不相同,强制用户每次开发时都要进行升级发布新版本。

这样的设计旨在使开发人员的生活变得轻松而不是用户的生活。每当用户不得不花时间升级他们没有要求并且可能不想要的好处时,您就需要从客户那里获得时间和资源。从开发人员到用户卸载时间和精力的设计是糟糕的设计,因为人们最终为了自己的利益购买软件。当您减少该利益时,您会降低软件的最终盈利能力。

因此,除非绝对技术必要,否则设计师不应设计强制用户做某事的用户不想做的事情的软件。这当然是一个经验法则,但它是一个非常好的。

答案 8 :(得分:4)

其他答案表明必须自己实施强制更新功能。 真的很遗憾,我希望不是这样。 我对iOS应用程序的第一次更新将于明天发布,幸运的是 它不会成为问题,因为我们只对应用程序进行了更改。 但是,当我们最终改变我们的Web服务的结构时,它将非常有用 能够强制更新,以便我们的服务器不必支持每个应用程序版本。

然而,有一种强制更新的替代方案,在这个帖子中似乎没有提及。 您可以让每个生成数据的Web服务调用都将模式附加到数据中, 它告诉应用程序应该如何在您的应用程序中反序列化数据。 这使您可以更改get-requests生成的数据结构,而不会破坏应用程序中的反序列化。 当然,这假设您编写的解释器本身不会改变,但是当它成熟时,这是一个有点合理的假设。

发布请求可能是&#34;架构&#34;通过互动。 有了这个,我的意思是在你提出的每个帖子请求之前,你都会询问如何调用最新的web服务。 您使用附加的架构处理指令,然后您实际调用Web服务。 从本质上讲,这意味着每个帖子请求都需要2个请求,但这可能没问题。

但是,无论您是实施强制更新还是模式解释,从第1天到应用程序商店时,该功能都必须存在于应用程序中。 否则你就会陷入同样的​​困境。如果Apple为我们的开发人员实施强制更新,则所有这些复杂性都是不必要的 如果存在强制更新,则模式解释仍然是可用性改进。 但它让我有点不知道苹果公司没有强制更新,因为至少有了它,人们可以在应用程序发布后引入自己的反破坏更新措施。

答案 9 :(得分:4)

由于这个原因,我对应用程序商店的应用程序更新完全被拒绝了。我们添加了一项功能来检查当前版本的已安装版本,如果它不是受支持的版本,我们会强制它们进行更新。

苹果拒绝了这一点。

回到设计委员会!

答案 10 :(得分:1)

对于未来的任何人,我发现本教程应该对任何人有所帮助,它帮助了我。

http://codewithchris.com/tutorial-how-to-implement-in-app-update-functionality-in-your-iphoneipad-app/

编辑(您的代码看起来类似于以下内容):

// Try to get version 
NSString *versionNumber = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];

NSURL *updateUrl = [NSURL URLWithString:@"http://yourdomain.com/yourupdatefile.xml"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:updateUrl
                                            cachePolicy:NSURLCacheStorageNotAllowed
                                        timeoutInterval:20.0];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest
                                     returningResponse:&response
                                                 error:&error];
// Check no error, then parse data
if (error == nil)
{
    // Parse response into a dictionary
    NSPropertyListFormat format;
    NSString *errorStr = nil;
    NSDictionary *dictionary = [NSPropertyListSerialization propertyListFromData:data
                                                                mutabilityOption:NSPropertyListImmutable
                                                                          format:&format
                                                                errorDescription:&errorStr];        
    if (errorStr == nil)
    {
        @try {

            // Try to see if the current app version exists in the update xml
            NSString *itunesUrl = [dictionary objectForKey:versionNumber];

            if (itunesUrl)
            {
                // Show dialog to ask user to update!
            }
            else {
                // Version not in XML
            }
        } @catch (NSException *e) {
            // Error with retrieving the key
        }
    }
    else {
        // Error with parsing data into dictionary
    }
}

然而,经过进一步研究,我发现如果您没有使用服务器,这将是一个很好的解决方案。

-(BOOL) needsUpdate{
    NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
    NSString* appID = infoDictionary[@"CFBundleIdentifier"];
    NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@", appID]];
    NSData* data = [NSData dataWithContentsOfURL:url];
    NSDictionary* lookup = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

    if ([lookup[@"resultCount"] integerValue] == 1){
        NSString* appStoreVersion = lookup[@"results"][0][@"version"];
        NSString* currentVersion = infoDictionary[@"CFBundleShortVersionString"];
        if (![appStoreVersion isEqualToString:currentVersion]){
            NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
            return YES;
        }
    }
    return NO;
}

在:

if (![appStoreVersion isEqualToString:currentVersion]){
                NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
                return YES;
            }

您设置的代码部分,如果它不相等,您可以将用户发送到应用商店以下载最新版本。

答案 11 :(得分:0)

您可以使用以下网址获取任何应用的信息 您只需知道自己应用的Apple ID。

您可以在itunesconnect.com&gt;您的应用&gt;应用信息页面中获取此Apple ID

获取:http://itunes.apple.com/lookup?id=

答案 12 :(得分:0)

您可以使用

检查应用程序内部版本号 <块引用>

Bundle.main.infoDictionary?["CFBundleShortVersionString"] 作为?字符串

然后与您的强制更新版本进行比较,以及是否要打开Appstore。

if let url = URL(string: "https://apps.apple.com/tr/app/--id--") {
    UIApplication.shared.open(url)
}

答案 13 :(得分:-10)

当然没有办法。用户应该决定是否要下载更新版本的应用程序。

AppStore会显示是否有新版本,所以我也不认为Apple会允许这样做。另外我不知道你会怎么做?您可以通过互联网连接查看,但这不是Apple喜欢的方式,因此您将没有机会这样做。