iOS中与Android Service相当的是什么?

9

随着iOS 7支持更广泛的后台模式,是否有可能在iOS上终于拥有等效于Android服务的功能?

我所追求的是,在后台运行应用程序A,并让一个或多个应用程序B和C与该应用程序通信(而不显示应用程序A的GUI界面)。

请注意,使用连接性和推送通知可能不是一种选择,尽管这是推荐的做法。有什么想法?


6
由于iOS7尚未发布,我建议您在其他地方提出这个问题。最好的地方是苹果开发者论坛。我怀疑苹果是否会允许您的应用程序在后台运行。因为太多愚蠢的程序员会编写耗电的垃圾服务。 - borrrden
嘿,我有一个类似的问题要解决...如果你已经解决了你的问题,请告诉我你是如何做到的? - Darth Vader
4个回答

6

编辑:无法按预期工作。请查看此答案以获取最佳解决方案:推送通知


编辑:下一个解决方案仅在用户在应用程序中时有用,以保持同步。

没有办法永久后台执行任务,但您可以使用有限长度的任务来执行操作,当您制作有限长度时,只要应用程序处于活动状态,它就会一直运行,但是当您单击主屏幕按钮时,iOS 仅给您10分钟来执行任务并使其无效,但它为您提供了一个机会,即可以制作“使其无效处理程序块”,在其中可以在最终完成之前执行最后一些操作。

因此,如果您使用该处理程序块调用其他时间的有限长度任务,则可以通过运行10分钟的任务来模拟服务,并在其结束时调用其相同的任务,然后再进行10分钟,依此类推。

我在创建一个名为“Service”的接口项目中使用它。这里是代码:


  • Service.h

//
//  Service.h
//  Staff5Personal
//
//  Created by Mansour Boutarbouch Mhaimeur on 30/09/13.
//  Copyright (c) 2013 Smart & Artificial Technologies. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Service : NSObject

@property (nonatomic) UIBackgroundTaskIdentifier backgroundTask;
@property (nonatomic) NSInteger frequency;
@property (nonatomic, strong) NSTimer *updateTimer;

- (id) initWithFrequency: (NSInteger) seconds;
- (void) startService;
- (void) doInBackground;
- (void) stopService;
@end

  • Service.m

//
//  Service.m
//  Staff5Personal
//
//  Created by Mansour Boutarbouch Mhaimeur on 30/09/13.
//  Copyright (c) 2013 Smart & Artificial Technologies. All rights reserved.
//

#import "Service.h"

@implementation Service
@synthesize frequency;

-(id)initWithFrequency: (NSInteger) seconds{
    if(self = [super init]){        
        self.frequency = seconds;
        return self;
    }
    return nil;
}
- (void)startService{
    [self startBackgroundTask];
}

- (void)doInBackground{
    //Español //Sobreescribir este metodo para hacer lo que quieras
    //English //Override this method to do whatever you want
}

- (void)stopService{
    [self.updateTimer invalidate];
    self.updateTimer = nil;
    [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
    self.backgroundTask = UIBackgroundTaskInvalid;
}

- (void) startBackgroundTask{
    self.updateTimer = [NSTimer scheduledTimerWithTimeInterval:frequency
                                                        target:self
                                                      selector:@selector(doInBackground)
                                                      userInfo:nil
                                                       repeats:YES];
    self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        [self endBackgroundTask];
    }];
}
- (void) endBackgroundTask{
    [self.updateTimer invalidate];
    self.updateTimer = nil;
    [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
    self.backgroundTask = UIBackgroundTaskInvalid;
    [self startBackgroundTask];
}

@end

我使用这个类来执行我的服务,但是我已经很长时间没有进行测试了。 我进行的最好的测试在模拟器上持续了16小时,一切都正常!

编辑:那是在模拟器上测试的,但是在手机上,在应用程序被终止后就无法工作。

我给你举个例子:


// SomeService.h
@interface SomeService : Service

@end


// SomeService.m
#import "SomeService.h"

@implementation SomeService

// The method to override
- (void)doInBackground{
    NSLog(@"Background time remaining = %.1f seconds", [UIApplication sharedApplication].backgroundTimeRemaining);
    NSLog(@"Service running at %.1f seconds", [self getCurrentNetworkTime]);
}
// Your methods
- (long) getCurrentNetworkTime{
    return ([[NSDate date] timeIntervalSince1970]);
}

@end

在您的应用程序委托或需要启动服务的位置,您将编写以下代码:

在你的AppDelegate或者需要启动服务的地方,你可以写下以下的代码:

Service myService = [[SomeService alloc] initWithFrequency: 60]; //execute doInBackground each 60 seconds
[myService startService];

如果您需要停止它:

[myService stopService];

可能解释得有点多,但我希望对任何人来说都清晰明了!希望这有所帮助,对我的英语表示抱歉。


我在真实设备上测试了我的解决方案,一切都运行良好,持续时间超过16小时。但是我遇到了一个问题,如果将频率设置为超过10分钟,则服务会运行,但计时器会在频率时间过去时执行代码,因此如果服务在执行代码之前失效,则在您的应用程序处于后台时永远不会执行它。所以我正在尝试解决它,如果有人解决了,请留下解决方案的评论! - IgniteCoders
这个解决方案是否符合苹果的审批要求? - Ahmed
我不知道,还在开发这个应用程序。只是遇到了问题,因为我在 iPhone 5C 上测试应用程序,服务在10分钟后停止了。:S - IgniteCoders
1
谢谢。我在iOS 6.1的iPhone 4S上尝试了这个。工作在十分钟时停止。虽然代码在时间结束后重新调用后台任务。有什么帮助吗 :O - Ahmed
有人得到解决方案了吗?这样我们就可以安排一个任务,在5天后发生,而且应用程序也不应在后台运行。我们是否可以使用iOS内部调度程序来实现,就像提醒中使用的那样? - Saty
显示剩余3条评论

2

没有类似于Android Service的东西。MansApps的代码不起作用,至少在iOS7上不行。在到期处理程序中调用[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];只会在应用回到前台时返回,也就是说,在应用保持在后台时,[self startBackgroundTask];将不会被执行。


我使用推送通知来解决这个问题,一切都运行得更好了。而我所创建的服务,则是为了在用户使用应用程序时进行刷新或获取内容。 - IgniteCoders

2
基本上,如果您的应用程序未实现下列任何功能,则几乎不可能实现。并且在上传到商店之前,他们很少调查您的应用程序,因此您需要证明使用该权限的必要性。
这是苹果对此的说法:
实施长时间运行的任务
对于需要更多执行时间来实现的任务,您必须请求特定权限才能在后台运行它们而不被暂停。在iOS中,只允许特定类型的应用程序在后台运行:
- 在后台播放可听内容的应用程序(例如音乐播放器应用程序) - 在后台记录音频内容的应用程序 - 始终通知用户其位置的应用程序(例如导航应用程序) - 支持互联网语音通信协议(VoIP)的应用程序 - 需要定期下载和处理新内容的应用程序 - 从外部配件定期接收更新的应用程序
实现这些服务的应用程序必须声明它们支持的服务,并使用系统框架来实现这些服务的相关方面。声明服务可以让系统知道您使用了哪些服务,但在某些情况下,确实是系统框架防止您的应用程序被挂起。

0

我找到了最好的标准解决方案:

推送通知

(原始帖子由Matthijs Hollemans发布,由Ali Hafizji更新)。

iOS中,应用程序不能在后台做很多事情。应用程序只允许进行有限的活动,以节省电池寿命。 但是,如果发生了一些有趣的事情,并且您希望让用户知道这一点,即使他们当前没有使用您的应用程序呢? 例如,也许用户收到了新的推文,他们最喜欢的团队赢得了比赛,或者他们的晚餐已经准备好了。由于应用程序当前未运行,因此无法检查这些事件。 幸运的是,苹果提供了解决方案。您可以编写一个服务器端组件来代替您的应用程序持续检查事件或在后台执行工作。 当发生感兴趣的事件时,服务器端组件可以向应用程序发送推送通知推送通知可以执行三个操作:

  • 显示短文本消息
  • 播放简短的声音
  • 在应用程序图标上设置数字
教程链接:http://maniacdev.com/2011/05/tutorial-ios-push-notification-services-for-beginners

原始问题明确指出推送通知可能不是一个选项,对于许多持续的后台处理或通信解决方案来说,它们远非最佳解决方案。 - Opsimath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接