2016-07-06 5 views
4

フォアグラウンドとバックグラウンドの両方にあるときに、場所の更新を使用するアプリがあります。 CoreLocationフレームワークを使用して、アプリケーションを実装して、thisコードを参照として5分ごとに位置の更新をサーバーに送信しました。iOSなぜシステムがバックラウンドの場所を使用してアプリを殺すのですか

これはフォアグラウンドでうまく動作しますが、アプリがバックグラウンドになると、30分から1時間後にOSによって強制終了されます。私は、バックグラウンドでさえも、少なくとも8時間更新を取得したい。

また、アプリは1時間あたり約10%のバッテリーを使用しています。これはバックグラウンドで殺されているアプリに関連していますか?もしそうなら、どのようにしてバッテリーの問題を解決できますか?それ以外の場合は、問題が何であるか教えてください。私は次の関数を使用してバックグラウンドタスクのために

Exception Type: 00000020 
Exception Codes: 0x000000008badf00d 
Exception Note: SIMULATED (this is NOT a crash) 
Highlighted by Thread: 2 

Application Specific Information: 
<BKNewProcess: 0x17e74840; com.app.app; pid: 560; hostpid: -1> has active assertions beyond permitted time: 
{(
<BKProcessAssertion: 0x17d78740> id: 560-C9E81E97-90D9-4F95-871E-3DC53372F302 name: Called by UIKit, from <redacted> process: <BKNewProcess: 0x17e74840; com.app.example; pid: 560; hostpid: -1> permittedBackgroundDuration: 180.000000 reason: finishTask owner pid:560 preventSuspend preventIdleSleep preventSuspendOnSleep , 
<BKProcessAssertion: 0x17e6a870> id: 560-BD7B29FC-DABC-42FF-AF17-B277BDB1C59D name: Called by UIKit, from <redacted> process: <BKNewProcess: 0x17e74840; com.app.example; pid: 560; hostpid: -1> permittedBackgroundDuration: 180.000000 reason: finishTask owner pid:560 preventSuspend preventIdleSleep preventSuspendOnSleep 
)} 

以下

は、デバイスのクラッシュログで

func backgroundTask(){ 
    var application=UIApplication.sharedApplication() 
    var background_task: UIBackgroundTaskIdentifier? 
    background_task = application.beginBackgroundTaskWithExpirationHandler({() -> Void in 
     application.endBackgroundTask(background_task!) 
     background_task = UIBackgroundTaskInvalid 
    }) 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {() -> Void in 
     //run the app without startUpdatingLocation. backgroundTimeRemaining decremented from 600.00 
     self.locationManager.startUpdatingLocation() 
     while (true) { 
      //backgroundTimeRemaining time does not go down. 
      print("Background time Remaining: \(UIApplication.sharedApplication().backgroundTimeRemaining)") 
      NSThread.sleepForTimeInterval(1) 

      break 
      //wait for 1 sec 
     } 
     application.endBackgroundTask(background_task!) 
     background_task = UIBackgroundTaskInvalid 
    }) 

} 

答えて

1

あなたは例外で終了していない任意のクラッシュlog.Ifアプリケーションを持っていますかいくつかの隠されたバグのあなたは記憶圧迫の疑いがあります。私はこの記事が突然終了の理由を見つけるためにあなたを導くだろうと思う。

https://www.raywenderlich.com/23704/demystifying-ios-application-crash-logs

+0

私は質問を更新しました。クラッシュログを持つ。 – Poonam

+0

8badf00dは、「アプリケーションがシステムイベントを起動、終了、または応答するのに時間がかかりすぎた」と知られています。 私はスレッド2のログインから、何かがメインスレッドで実行するには時間がかかりすぎることを理解しています。 –

+0

また、アプリケーションがバックグラウンドで常に実行されている場合は、バックグラウンドモードを使用することを検討してください。バックグラウンドで長くしてください。 –

2

アプリがバックグラウンドで入力すると、significant location updatesに切り替わり、アプリは継続的に位置情報の更新を受け取ります。 CLLocationMangerのオブジェクトにはstartMonitoringSignificantLocationChangesと呼ぶことができます。私はバックグラウンドタスクを確立する必要はありません。

Apple Documentationをチェックし、それはあなたがこのサービスを開始し、アプリがその後に終了した場合は、新しいイベントが到着した場合、システムが自動的にバックグラウンドにアプリをrelaunches、

を述べています。そのような場合、アプリケーションに渡されるオプション辞書:willFinishLaunchingWithOptions:およびapplication:didFinishLaunchingWithOptions:アプリケーション代理人のメソッドには、UIApplicationLaunchOptionsLocationKeyキーが含まれているため、アプリケーションがロケーションイベントのために起動されたことを示します。再起動時には、依然としてロケーションマネージャオブジェクトを設定し、このメソッドを呼び出してロケーションイベントの受信を継続する必要があります。ロケーションサービスを再起動すると、現在のイベントがすぐにデリゲートに配信されます。さらに、ロケーションマネージャオブジェクトのlocationプロパティには、ロケーションサービスを開始する前であっても、最新のロケーションオブジェクトが設定されます。

したがって、あなたの問題を解決し、バッテリーの問題も解決します。

長時間バックグラウンドで場所を更新する場合は、DesiredAccuracykCLLocationAccuracyBestを設定しないでください。 kCLLocationAccuracyThreeKilometersDesiredAccuracyと設定して、setDistanceFilter99999のような非常に大きな桁にバックグラウンドで入力すると設定できます。

this so postthis so postを参照できます。

希望@Lionがバックグラウンドで入力する際重要な場所の変更を使用して言ったように、これは:)

1

をするのに役立ちます。私はSLCを使って同じ問題を抱えていたので、あなたもそれを持っています。アプリがバックグラウンドに入ったとき、メモリ警告のためにシステムによって殺されました。だから私がしたのは、CoreLocationのすべての代理人呼び出しを受け取るCoreLocation用のシングルトンを作成することでした。それは殺されています場合には、バックグラウンドであなたのサービスを再起動するために

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) { 

     //NSLog(@"Restarting SCL"); 
     LocationService *loc = [LocationService sharedInstance]; 
     [loc setManagedObjectContext:self.managedObjectContext]; 
} 

LocationServiceは私のシングルトンです。

も、メモリの警告通知を処理するためにAppDelegateでこの機能を実装します。

-(void)applicationDidReceiveMemoryWarning:(UIApplication *)application 
{ 
    //Sending notification to every controller to free some memory 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"freeMemory" object:nil userInfo:nil]; 

    SDImageCache *imageCache = [SDImageCache sharedImageCache]; 
    [imageCache clearMemory]; 
    [imageCache clearDisk]; 

    //NSLog(@"Received memory warning!"); 
} 

例えば画像のキャッシュをクリアします。 また、MapViewを使用しているため、非常に高価なビュー(およびリークのバグ)があるので、使用しないものは無効にしてください。

0

その他の点として、バックグラウンドの場所の更新を受け取るために登録する必要があります。明確でないかもしれないのは、これが「あなたの気持ちが何であれ、いつもバックグラウンドで走っている」と同じことではないということです。つまり、システムの裁量により、さまざまなタイミングで場所データが送信されるため、できるだけ早くその場所データを処理してから返却する必要があります。システムが選択すると、あなたは再び呼び出されます。他の位置情報サービスが実行されている可能性があります。システムは、すべての異なるロケーションクライアントを統合することによって、これを最適化しようとします。

あなたが使用しようとしているようなバックグラウンドタスクは、まったく別の問題です。彼らは、ユーザーがアプリを終了したときに何かをするために「少し余分な時間」を要請します。あなたのデータベースなどを整理するようなもの。あなたがそれらを走らせ続けるなら、あなたは殺されるでしょう。あなたの現在のコードを見ると、1回の呼び出しの後にループから壊れるように見えるので、実際には何もしないように見えます。しかし、NSThread.sleepForTimeInterval(1)を呼び出すコードは、iOSではほとんど間違っていることが保証されています。その呼び出しを行う理由はほとんどありません。しかし、ロケーションアップデートを管理するためのバックグラウンドタスクは必要ありません。

関連する問題