iOSでbackground定周期処理の実際のところ【’24.7月編】

iOS で background ( 端末画面が非表示のとき ) 処理を定期実行させることは鬼門のようです。Appleの情報、ネット記事、有識者の情報 どれも幾分違っていて真実が分かりません。iOSではバッテリ節約が最優先され、background 処理時間に制限が厳しいと言われているようです。 ’24年7月に実装した結果を報告します。

OSiPadOS 17.6
端末iPad 6th
Xcode実機TEST 15.1 、シュミレータTEST 14.2
言語Swift UI

基本 background は「アプリが前面に表示されていないが動作しているとき」ですが、完全なbackground状態にするには以下の配慮が必要なようです。

  • iOS系は 画面スリープ無し に設定できますが、これは有効にしないこと。
  • USBで電源供給したままにしない。
  • Xcodeと接続しない。

またプログラムに、

  • トレースログが取得できる仕組みを作成しておく。

取り掛かりとしてApp の onChange(of:scenePhase) イベント で background と foreground の切替りを検出してました。そのbackground のifスコープにで タイマーをつっこみました。(以下赤字部) これが一番シンプルかなと…カンで組んでみました。

一見動作しているように見えたのですが、途中でお亡くなりになるようです。background に移行してから動作可能な時間制限があるとのことですが、正確にどのくらいか色々試してもよく分かりませんでした。 UIApplication.shared.beginBackgroundTask ~endBackgroundTask を使って時間制限を検出しリカバリする方法も試しましたが、なんだか効果なしです。BGTaskScheduler というのもありますが有識者によると、「定周期background 処理は基本的ニ出来ない」とのことで試さずじまいです。

iOSで background 処理を定期的に行う手法として、GPSによる中心座標からの半径範囲(リージョン)への出入りを検出する方法が、いろいろと紹介されています。これは XamarinのiOS Background処理の説明ページにも記載されています。概念図は以下の通りです。

もちろんこれが適用されるのは、端末がある程度の時間経過とともに移動するシステムに限ります。その検出部のコードは以下のような感じです。

ポイントとしては、

  • 移動しないとBackground実行できません。
  • 定周期でBackground実行する場合は、移動量と時間のCONVERTが必要です。
  • 半径5mに指定しても、イベント発生させるには50~100mくらい移動を要します。
  • UIApplicationDelegateAdaptor を Appクラスで絡めるコード例もありますが、シンプルに CLLocationManager だけで構築できます。

リージョン出入り検出」は、秒、分単位の定周期処理とすると不向きのようです。通常、リアルタイム緯度経度の検出で使用しているCLLocationManager のイベントも、よく観察するとBackground時でも動作していることに気付きました。リアルタイム緯度経度検出 と Background処理を一緒に行えば、もっと早い周期でBackground処理が可能となります。その検出部のコードは以下のような感じです。

ポイントとしては、

  • 移動しないとBackground実行できません。
  • 定周期でBackground実行する場合は、移動量と時間のCONVERTが必要です。
  • 移動距離をもっと小さくすると、秒周期でBackground内でイベント発生させることも可能。(iPadではGセンサも併用している模様)
  • 日中での電池の持ち、iPadなら電池の持ちは心配ない感じ。iPhoneは厳しい感じ。
  • 移動イベント中に、新しい移動イベントが発生した場合、新しい移動イベントは保留される。(保留最大数は未知)
  • リージョン出入り検出と同居可能。

Background内である程度の周期で動作できるようになったら、何秒くらい動作可能か情報が必要です。これも色々な説があるようです。以下のBackground処理ダミーコードで調べてみました。下記コード中の printLog はローカルtxtファイルへの出力付きの print 関数の自作ラッパーです。5秒置きにlogを残すことでどこまで動けるか確認しました。

結果としては、

  • 最小で45秒までは動けてはいた。公称値が30秒とのウワサ。
  • 最大120秒程度まで伸びる場合あり。CPU使用時間が影響しているのかもしれない。
  • 許容時間超過後、TASKは休止状態となり、Foregroud移行後に動き出す。
  • 製品コードでのBackground処理はScokect通信です。これはうまくいきました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です