【问题标题】:Can I force an iPhone user to upgrade an application?我可以强制 iPhone 用户升级应用程序吗?
【发布时间】:2011-01-14 08:28:51
【问题描述】:

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

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

【问题讨论】:

  • 作为 iPhone 用户,我见过很多糟糕的更新。我更愿意选择是否更新。甚至苹果和微软也不强制进行安全更新。您始终可以选择退出或恢复旧版本。如果它是安全或功能要求,您可以告诉您的用户更新是必要的,否则应用程序将无法运行。您可以在他们更新之前阻止他们的凭据,但这仍然是他们的选择。你给我一个糟糕的更新,我会删除它并从iTunes中恢复旧的。即使是现在,用户也已经提出了 iPhone 请求以阻止应用更新。
  • 我自己遇到这个问题已经有一段时间了。我发布了这个名为 Harpy 的小工具,它可以根据 App Store 版本检查已安装的版本。如果商店中有更新的版本,它会通知您的最终用户并在您的应用程序启动时提示他们下载该应用程序。 Grab it on Github.
  • 我有一个应用程序处于相同的情况;它具有版本检查逻辑,因为我们希望能够在需要/需要时进行强制升级。 iTunes 拒绝了早期的 beta 版本,因为它具有这种逻辑。我不明白的是,如果将 Harpy 用于 IOS 应用程序并且只向用户提供更新选项,那会被允许吗,为什么?当我查看 Harpy github 信息时,如果“更新”是唯一提供的选项(类似于我们拒绝的选项),我看不到避免更新的方法。 iTunes 作为主要信息源与外部信息源的重要区别是什么?

标签: iphone app-store-connect


【解决方案1】:

Apple 没有提供任何自动化的方式来完成,您必须手动编写。

选项 1. 可以使用 iTunes API 检查该特定 App id 的最新版本。并显示弹出窗口以更新应用程序。 选项2:您可以使用自己的服务器检查最新版本。但是每当有任何更新进入苹果应用商店时,您都必须更新您的服务器。

【讨论】:

    【解决方案2】:
    func appUpdateAvailable() -> (Bool,String?) {
            
            guard let info = Bundle.main.infoDictionary,
                  let identifier = info["CFBundleIdentifier"] as? String else {
                return (false,nil)
            }
            
    //        let storeInfoURL: String = "http://itunes.apple.com/lookup?bundleId=\(identifier)&country=IN"
            let storeInfoURL:String = "https://itunes.apple.com/in/lookup?bundleId=\(identifier)"
            var upgradeAvailable = false
            var versionAvailable = ""
            // Get the main bundle of the app so that we can determine the app's version number
            let bundle = Bundle.main
            if let infoDictionary = bundle.infoDictionary {
                // The URL for this app on the iTunes store uses the Apple ID for the  This never changes, so it is a constant
                let urlOnAppStore = NSURL(string: storeInfoURL)
                if let dataInJSON = NSData(contentsOf: urlOnAppStore! as URL) {
                    // Try to deserialize the JSON that we got
                    if let dict: NSDictionary = try? JSONSerialization.jsonObject(with: dataInJSON as Data, options: JSONSerialization.ReadingOptions.allowFragments) as! [String: AnyObject] as NSDictionary? {
                        if let results:NSArray = dict["results"] as? NSArray {
                            if let version = (results[0] as! [String:Any])["version"] as? String {
                                // Get the version number of the current version installed on device
                                if let currentVersion = infoDictionary["CFBundleShortVersionString"] as? String {
                                    // Check if they are the same. If not, an upgrade is available.
                                    print("\(version)")
                                    if version != currentVersion {
                                        upgradeAvailable = true
                                        versionAvailable = version
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return (upgradeAvailable,versionAvailable)
        }
    

    【讨论】:

      【解决方案3】:

      您可以检查应用程序内部版本号

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

      然后与你的强制更新版本比较,如果你想打开 Appstore。

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

      【讨论】:

        【解决方案4】:

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

        * 编辑 * 这个答案不再正确。查看当前事实的其他投票答案。

        【讨论】:

        • 感谢您的解释。我必须尝试一下,因为我的应用程序必须进行明确的升级。当前版本涉及免费订阅,升级必须包括付款。这就是我试图强迫它的原因。
        • @HariKaramSingh,是的,您可以使用其他问题中提到的方法。不幸的是,当它被标记为已接受时,我无法删除此答案
        【解决方案5】:

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

        您可以在itunesconnect.com>您的应用>应用信息页面获取此 Apple ID

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

        【讨论】:

          【解决方案6】:

          这个问题最初是在 7 年前发布的,虽然其中一些答案仍然相关,但这里有一个更新的方法。

          我推荐https://github.com/ArtSabintsev/Siren,它与 Swift 3 兼容,可以与 Cocoapods 或 Carthage 一起安装。

          CocoaPods、Swift 3 支持:

          pod 'Siren'

          迦太基:

          github "ArtSabintsev/Siren"

          【讨论】:

            【解决方案7】:

            正是由于这个原因,我对 App Store 的应用更新被拒绝了。我们添加了一项功能,可以根据当前版本检查已安装的版本,如果它不是受支持的版本,我们会强制它们进行更新。

            苹果拒绝了。

            所以回到设计板!

            【讨论】:

            • 我很好奇,他们有没有说明这违反了哪条 App Store 指南?
            • 我有一个应用程序处于相同的情况;它具有版本检查逻辑,因为我们希望能够在需要/需要时进行强制升级。早期的测试版因具有这种逻辑而被拒绝。知道为什么不允许您的应用程序的版本检查逻辑,但从各种帖子看来,harpy 是允许的?
            • 如果他们始终使用最新版本进行测试,他们究竟是如何发现您显示此屏幕的?
            • 我们还在我们的 iOS 应用程序中提供了强制更新功能,该功能检查 Web 服务的最低支持版本并在需要时强制更新。它从未被拒绝。
            【解决方案8】:

            你好,以后的任何人我发现这个教程应该可以帮助任何人,它帮助了我。

            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;
                        }
            

            您设置的代码部分如果不相等,则您要执行的操作,这是您将用户发送到应用商店以下载最新版本的位置。

            【讨论】:

            • 你能告诉我我必须将那部分代码放在我们的应用程序中的什么地方吗?是否有必要放入 didfinish 启动选项或其他地方?请指导我
            • @BhupatBheda 抱歉,回复晚了。从 GIT 克隆此代码,它将帮助您更好地理解。 github.com/ArtSabintsev/Harpy 当您将代码迁移到项目中时,您需要获取 harpybundle、harpy.h 和 harpy.m 就是这样,您需要从那里对您的 appdelegate 进行更改(复制并粘贴相同的内容他们在您的应用程序委托中)。您将在“HarpyAlertType”中有一个选项,您将在项目中看到它,单击您要在更新应用程序时向用户展示的选项。然后你可以忘记它。这将通过子。
            • @BhupatBheda HarpyAlertType 您将拥有三个选项: HarpyAlertTypeSkip HarpyAlertTypeForce HarpyAlertTypeOption 选择您希望显示的一个。我希望我没有太晚并且能够提供帮助,再次为我在假期中的迟到回复感到抱歉。
            • 嘿,谢谢您的回复,我会尽力按照您提到的那样做谢谢!
            【解决方案9】:

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

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

            发布请求可以通过交互“模式化”。 我的意思是,在您提出每个后请求之前,您会询问有关如何调用最新 Web 服务的说明。 为此,您使用附加的模式处理指令,然后对 Web 服务进行实际调用。 本质上,这意味着每个 post 请求都需要 2 个请求,但这没关系。

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

            【讨论】:

              【解决方案10】:

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

              这可能而且应该是 Apple 和 Google 提供的东西,但它们并不是这样的,所以除了一些游戏之外的每个应用程序都需要构建它,所以...

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

              在 GitHub 上:https://github.com/SlalomDigital/ApplicationCtrl

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

              【讨论】:

                【解决方案11】:

                您可以检测应用是否需要更新,然后采取一些自定义操作,例如提醒用户有可用更新。这是一个检测更新可用的代码 sn-p。

                -(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;
                }
                

                【讨论】:

                • BundleIdentifier 可能会在每个下一个版本中更改。最好使用“App ID”,因为它不会改变。
                • 澄清@GaneshGuturi 的评论:将lookup?bundleId= 替换为lookup?id=。并使用您的应用程序的“Apple ID”,而不是查找捆绑标识符。所以url =之前的两行就不需要了;只需从应用的 iTunes 连接页面硬编码“Apple ID”即可。
                • 这是一个很好的答案,使用 [appStoreVersion compare:currentVersion options:NSNumericSearch] == NSOrderedDescending 之类的东西来比较两个版本也可能是可取的,例如,如果您想避免潜在的 App Store 审核问题,因为审核中的版本将始终与 App Store 版本不同。当然,这仅在您增加每个版本的版本时才有效(不是从版本 2.0.0 到 1.0.0)。
                【解决方案12】:

                我通过从 iTunes 网络服务获取版本并与当前版本进行比较来完成此功能。以下是我的代码

                        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];
                        }
                

                并将应用程序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 服务调用..

                【讨论】:

                • 这真是太好了。你还在使用上面的概念吗?或者有什么限制吗? @Dilip Rajkuma
                • 嗨 @ganesh 我不是在开发 iOS 应用程序。但我想它仍然可以工作,如果没有,请告诉我..
                • 恕我直言,对于这种情况,网络服务机制似乎有点矫枉过正。参见@datinc 的[NSData dataWithContentsOfURL:url]。但如上所示使用lookup?id=&lt;Your app ID&gt;,而不是 datinc 的 `lookup?bundleid=.."。
                • 但是当应用程序处于“审查中”状态时,苹果将如何审查,因为它每次都显示警报。我说的对吗?
                • @DilipRajkumar,但是当应用程序处于“审查中”状态时,苹果将如何审查,因为它每次都显示警报。我说的对吗?
                【解决方案13】:

                您的业务/设计计划绝不应包含“强迫用户”一词。当你让他们做某事时,他们会生气。想象一下,一个用户匆匆忙忙地打开了你漂亮的小应用程序,却发现你在强迫他升级,然后他才能使用应用程序来满足他的需要。想象一下,他不得不使用 Edge 下载。他不会高兴的。

                如果您遵循此计划足够长的时间,您的其中一项升级将不可避免地引入一个明显的错误。如果你强迫用户使用有缺陷的版本,他们会反抗。

                每当我看到用于描述新版本软件的“更多功能”时,我都会因经验而畏缩,因为这不可避免地意味着功能膨胀。设计师倾向于不断将越来越多的功能移植到应用程序上,直到一个应用程序完成所有工作。这在像 iPhone 这样的平台上尤其危险,因为让一个应用程序做很多事情会迅速压倒应用程序的界面和响应能力。

                Edit01:我在How to Update an Application After Users Pay For Upgrade 的评论也可能与您的计划有关。如果您的升级设计将 Apple 排除在收入循环之外,那么它就不是首发了。

                更新:

                根据下面的评论澄清一下:是的,有时您确实必须要求用户升级。然而,这与设计应用程序从一开始强制用户每次升级开发者有很大不同发布新版本。

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

                因此,任何设计师都不应该设计强迫用户做用户不希望做的事情的软件,除非这是绝对的技术需要。这当然是一个经验法则,但它是一个非常好的法则。

                【讨论】:

                • 我同意“强迫用户”是非常糟糕的行为。但是,在某些情况下,强制更新路径可能是相关的。例如,我来寻找这个答案是因为我有一个基于多用户持久服务器的游戏(有点像 MMORPG),并且每当我向服务器添加可能不兼容的功能时,我都需要强制更新旧版本。然而,这是一个奇怪的用例。大多数时候可以设计出更好的解决方案。
                • 我不同意,强迫用户更新总是一个坏主意。如果您正在制作游戏,而用户发现了一个可以让他们提高在线分数或成就的漏洞怎么办?如果开发者修复漏洞并发布更新,作弊者不会“想要”升级,因为他们知道更新会阻止他们作弊。如果您不能强制更新,那么如何防止作弊者使用该漏洞?你不能!对于所有喜欢你的游戏并选择不作弊的玩家来说,这将是一场灾难,他们只会停止玩游戏。你的想法?
                • 我不同意,当然,你需要强迫用户更新几次。
                • 我不明白为什么这篇文章得到了如此多的支持。 OP 并没有问“我应该强迫 iPhone 用户升级应用程序吗?”所以这个回复没有解决这个问题,只是一个观点。您需要强制用户升级有很多正当理由。看看 Xbox Live,它已经投入生产多年,拥有非常庞大的用户群。它要求用户在每次有新更新可用时更新仪表板。
                • 我对这个答案投了反对票。我不傻,我不需要说教的答案。我知道在没有充分理由的情况下强迫用户做某事不是一个好主意。我碰巧有一个非常很好的理由去做这件事,我来到这里是希望找到完成它的最佳方法。
                【解决方案14】:

                如果您绝对需要,您可以启动 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]];
                

                【讨论】:

                • 但是如何确定商店中的是否是更新版本?
                • @ToolmakerSteve - 您可以从 iTunes 页面抓取最新版本,或者更轻松地保留最新版本的小 html 文件并从您的客户端进行检查。除了其他方式。
                【解决方案15】:

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

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

                【讨论】:

                • 我不同意,强迫用户更新总是不是一个坏主意。如果您正在制作游戏,而用户发现了一个可以让他们提高在线分数或成就的漏洞怎么办?如果开发者修复漏洞并发布更新,作弊者不会“想要”升级,因为他们知道更新会阻止他们作弊。如果您不能强制更新,那么如何防止作弊者使用该漏洞?你不能!对于所有喜欢你的游戏并选择不作弊的玩家来说,这将是一场灾难,他们只会停止玩游戏。你的想法?
                • 思维方式还可以,但如果可以强制更新,用户就会失去控制,那就不好了。这是用户的设备,他可以决定他想用它做什么。
                • :)) “这是用户的设备,他可以决定他想用它做什么” - 就好像苹果让你用你的设备做你想做的事。
                • 有时你必须像我最近在一个医疗应用程序中一样,你确定你想要一个错误剂量的应用程序给你的孩子用药?! :)
                • 没有办法是什么意思?您始终可以通过要求 GPS 数据访问来跟踪用户,然后去那里用枪指着他的头,迫使他更新应用程序。说真的,当然你不能强迫用户做任何事情,但作为应用程序所有者,你当然可以提供选择:更新或保留应用程序的无用版本——仅仅因为它是我的应用程序,我必须做出决定。你知道吗 - 我真的这样做是因为我为我的用户增加了更多价值,并且不想在更新需要几秒钟的世界中浪费时间在向后兼容性上。
                【解决方案16】:

                没有自动化的方法可以做到这一点,你必须手动编写一些东西。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-04-09
                  • 2010-10-11
                  相关资源
                  最近更新 更多