iOS では、アプリがフォアグラウンドになくてもアプリを実行し続けるように OS に指示するにはどうすればよいですか?
そして、さらに多くのアプリがこれを行います。
iOS では、アプリがフォアグラウンドになくてもアプリを実行し続けるように OS に指示するにはどうすればよいですか?
そして、さらに多くのアプリがこれを行います。
基本的に、iOS にはサービス型のアプリや機能といったものはありません。「バックグラウンド」アプリ (UIBackgroundMode) でさえ、完全に無料で実行することはできず、他の OS のサービスやデーモンなどの制限なしで実行できます。
バックグラウンド実行や通知・タイマーなどの状況はこちら。
1) 次の場合を除き、アプリはバックグラウンドで実行できません。
a) そのために OS に追加の時間を要求します。これは、beginBackgroundTaskWithExpirationHandler を使用して行われます。この余分な時間の長さは (意図的に) Apple によって指定されていませんが、実際には約 10 分です。
b) アプリにはバックグラウンド モードがあり、モードは VoIP、オーディオ、ロケーション、ニューススタンドです。これらのタイプのいずれかであっても、アプリは制限なしでは実行できません。この説明の残りの部分では、アプリにバックグラウンド モードがないことを前提としています。これらのバックグラウンド モードのいずれかを使用してアプリをバックグラウンドで実行できるようにしようとしたが、アプリが特定の機能を正当に使用していない場合、アプリはアプリ ストアへの送信時に拒否されます (つまり、UIBackgroundMode を持つため)。 VoIP アプリ、位置情報を継続的に更新する必要がある、バックグラウンドでオーディオを継続的に再生する機能が基本的な機能である、またはニューススタンド アプリである必要があります)。
2) アプリが一時停止されている場合、アプリ自体を直接起動することはできません。以前に NSTimer をスケジュールすることはできず、performSelector:afterDelay などを使用することはできません。等
アプリが再びアクティブになる唯一の方法は、ユーザーがアプリをアクティブにするために何かを行った場合です。ユーザーは、次の方法でこれを行うことができます。
a) アプリをアイコンから直接起動する
b) アプリがアクティブである間にアプリによって以前にスケジュールされたローカル通知に応答して、アプリを起動します。
c) サーバーから送信されたリモート通知に応答してアプリを起動します。
d) その他いくつか: アプリが URL 経由の起動を処理するように登録されている場合の URL 起動など。または、特定の種類のコンテンツを処理できるように登録されている場合。
ローカル/リモート通知が発生したときにアプリがフォアグラウンドにある場合、アプリはそれを直接受け取ります。
ローカル/リモート通知が発生したときにアプリが現在フォアグラウンドにない場合、アプリはそれを受け取りません。通知が発生したときに実行されるコードはありません。
ユーザーが通知を選択した場合にのみ、アプリがアクティブになり、実行できます。
ユーザーは、デバイス全体または特定のアプリケーションのみの通知を無効にできることに注意してください。この場合、ユーザーには通知が表示されません。通知が火災によるものであるときにデバイスの電源を切ると、通知は失われます。
1)バックグラウンドフェッチなどの新しいバックグラウンドモードがいくつかあります(ただし、決定論的な方法でOSによって呼び出されることはまだありません)
2) バックグラウンドでのプッシュ通知ができるようになりました
3) beginBackgroundTaskWithExpirationHandler の時間が 10 分から約 3 分から短縮されました。
iOS7では状況が変わり、現在はベータ版です。
iOS 7 で新しいマルチタスク API を採用することにより、アプリのコンテンツを最新の状態に保ちます。新しいサービスを使用すると、アプリは情報を更新し、バッテリーを不必要に消耗させることなくバックグラウンドでコンテンツをダウンロードできます。更新は日和見的なタイミングで行われ、使用状況に応じてインテリジェントにスケジュールされるため、アプリはユーザーが必要とするときにバックグラウンドでコンテンツを更新できます。
はい、これを行うことができます。
ステータスを追跡するプライベート フィールドを作成します。
UIBackgroundTaskIdentifier _bgTask;
このメソッドを呼び出して、アプリをサービスのように実行します
if ([[UIDevice currentDevice] respondsToSelector:@selector(isMultitaskingSupported)])
{
_bgTask = UIBackgroundTaskInvalid;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(doBackground:)
name:UIApplicationDidEnterBackgroundNotification object:nil];
}
次に、セレクターを作成します-
- (void) doBackground:(NSNotification *)aNotification
{
UIApplication *app = [UIApplication sharedApplication];
if ([app respondsToSelector:@selector(beginBackgroundTaskWithExpirationHandler:)])
{
_bgTask = [app beginBackgroundTaskWithExpirationHandler:^
{
dispatch_async(dispatch_get_main_queue(), ^
{
if (_bgTask != UIBackgroundTaskInvalid)
{
[app endBackgroundTask:_bgTask];
_bgTask = UIBackgroundTaskInvalid;
}
});
}];
}
}
タスクが完了したら、以下のコードを呼び出します-
UIApplication *app = [UIApplication sharedApplication];
if ([app respondsToSelector:@selector(endBackgroundTask:)])
{
if (_bgTask != UIBackgroundTaskInvalid)
{
[app endBackgroundTask:_bgTask];
_bgTask = UIBackgroundTaskInvalid;
}
}