バックグラウンドでiOSアプリを実行する

タスクは、ユーザーが指定した間隔でプログラムがWebソケットを介して現在の座標を送信することでした。 さらに、プログラムはバックグラウンドで動作する必要があります。何らかの理由でユーザーまたはiOSがメモリからアンロードした場合、プログラムを再起動してバックグラウンドで動作し続けることをお勧めします。
タスクセットは、サーバー側を変更せずにiOSによってのみ解決する必要があります(プッシュ通知なし)。

プログラムがバックグラウンドに最小化されているときにタイマーで座標を送信することは問題ではありません。このため、 バックグラウンドロケーションモードを使用して、座標とタイマーの長時間実行タスクを取得できます。

しかし、iOSにはAndroidバックグラウンドサービスのような魅力がないため、プログラムを手動で終了すると、コードの実行が停止します。 したがって、主な困難は、プログラムをバックグラウンドでできるだけ速く実行する方法にあります。そのため、何らかの理由でiOSメモリからアンロードされた場合、ユーザーがデバイスを再起動した場合、または手動でプログラムを「殺した」場合、タスクをさらに実行し続けることができます

次に、この問題を許容可能な方法で解決するのに役立ったものについて:

-VOIPバックグラウンドモード
このバックグラウンドモードがオンになっている場合、デバイスを再起動した後、または何らかの理由でiOS自体のメモリからプログラムがアンロードされた場合、iOSはアプリケーションを再起動します。
また、プログラムがバックグラウンドに最小化されている場合、このモードは、NSStreamNetworkServiceTypeVoIPフラグでマークされた接続ソケットを閉じないようiOSに指示します。
例:

[NSStreamInstance setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType]; 

ただし、ユーザーがプログラムをメモリから手動でアンロードすると、終了コードがゼロで終了し、iOSが接続ソケットを閉じ、その後プログラムは再起動しません。
実践が示すように、iOSは、iOS自体のメモリからアンロードされた場合、プログラムを常に再起動するわけでもありません。

-重要な変更場所
メモリからアンロードされた場合、座標変更のイベントでプログラムをバックグラウンドで再起動します。 この方法は完全に信頼できるものではありません。どの場合にiOSがプログラムをバックグラウンドで起動するかを予測することは困難です。これは、プログラムが終了した直後、またはかなりの期間後(特にデバイスに触れない場合)に発生する可能性があります。
このサービスを有効にするには、次のメソッドを呼び出します。

 [CLLocationManagerInstance startMonitoringSignificantLocationChanges]; 

-地域モニタリングの場所
これらのイベントが発生した場合にiOSがプログラムを監視および起動する入口または出口で地域を指定できます。
したがって、追加の手段として、ユーザーがプログラムをメモリからアンロードするときに、applicationWillTerminateイベントによって、現在の座標の中心と半径5メートル(最小値)で追跡する領域を設定します。 そして、練習が示すように、ユーザーが特定の地域の中心から100メートル離れた場所に移動すると、iOSはdidExitRegionイベントでプログラムを再起動します。

この方法は、重要な変更場所よりもはるかに正確かつ確実に機能します。
例:

 @implementation AppDelegate - (void)applicationWillTerminate:(UIApplication *)application { CLCircularRegion* region = [[CLCircularRegion alloc] initWithCenter:userLocaton.coordinate radius:5 identifier:@"wakeupinbg"]; region.notifyOnEntry = YES; region.notifyOnExit = YES; [CLLocationManagerInstance startMonitoringForRegion:region]; } @end 

-ローカル通知
プログラムがメモリから突然アンロードされ、再起動しない場合にユーザーに通知するために使用されます。
次のように機能します。
1)10分後に鳴るローカル通知が設定されます
2)タイマーが設定され、7分ごとにカチカチと音が鳴り、ローカル通知が鳴るまでの残り時間がチェックされます
3)ローカル通知までの残り時間が4分未満の場合、プログラムは現在のローカル通知を削除し、新しいローカル通知を設定します(ポイント1)
4)何らかの理由でプログラムが突然アンロードされた場合、タイマーはそれに応じて実行されず、ローカル通知はリセットされません(ポイント3は実行されません)プログラムはメモリからアンロードされ、起動する必要があります。

これらのアプローチを使用するいくつかの重要なポイント:

-プロジェクト設定の[機能]タブでバックグラウンドモードを有効にすることを忘れないでください:



-NSLocationAlwaysUsageDescriptionフィールドをinfo.plistに追加する必要があります。



-CLLocationManagerを作成した後、ユーザーから座標を取得する許可を要求する必要があります。

 [CLLocationManagerInstance requestAlwaysAuthorization]; 

-iOS9では、CLLocationManagerオブジェクトのバックグラウンドで座標の取得を有効にする必要があります。

 if ([CLLocationManagerInstance respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) { [CLLocationManagerInstance setAllowsBackgroundLocationUpdates:YES]; } 

実行して、このソリューションがどのように機能するかをより詳細に確認できるテストプロジェクトはこちらです: github.com/vaskravchuk/BGModesTest
また、同様のソリューション(voipなしのみ)を備えたアプリケーションが市場に出ています: Track-kit

PS顧客はApple Developer Enterprise Programを使用しています。つまり、プログラムはAppleによってテストされないため、この問題の可能性は考慮されていません。

PSSプログラムをバックグラウンドで維持する問題を解決する最善の方法に関する情報があれば、私は非常にうれしく思います。

Source: https://habr.com/ru/post/J271505/


All Articles