2

私のアプリは、ブロードキャスト イベント (HEADSET イベント) をリッスンし、それに応じて動作する必要があります。フラグ FLAG_RECEIVER_REGISTERED_ONLY がこのイベントに対して有効になっているため、ミニフェスト レシーバー経由で HEADSET イベントを使用できないことがわかりました。したがって、プログラム内で動的にこのイベントにのみ登録できます。イベント中はアプリがアクティブにならないため、このイベントを処理するサービスが必要でした。onCreate で登録し、onDestroy で登録解除します。ここまでは順調ですね。サービスを実装してテストを開始したところ、リソースが不足した場合にシステムによってサービスが強制終了され、システムが自動的にサービスを再起動することがわかりました。ただし、驚くべきことは、キルと再起動の間の遅延です。これは完全にランダムであり、巨大になる可能性があります. 秒単位の場合もあれば、時間単位の場合もありました。そう、

さまざまな提案があったことについてstackoverflowを閲覧しました。何もしないダミー スレッドを用意します。これにより、サービスの「重要性」が高まります。startForeground でサービスを使用すると、通知が発生します。これらはすべて回避策のように見えますが、絶対確実ではありません。

これを誰にでもできる方法で解決する方法はありますか?「REGISTERED_ONLY」ブロードキャストイベントを処理するための代替ソリューションは何ですか?

ありがとう。

4

1 に答える 1

6

私は多くの試行錯誤のプログラミングを行い、これに対する解決策を見つけました。だから、私は自分の質問に答えます。

サービス再起動時の Android の動作: リソース不足が発生した場合に、Android サービスがシステムによって強制停止されることはよく知られています。Android はこのサービスを自動的に再起動します。これは避けられないことであり、このシナリオを適切に処理するようにサービスをプログラムする必要があります。サービスの強制停止と再起動の間に遅延があることに注意してください。この遅延は一見ランダムで、数時間かかる場合があります。この遅延にはパターンがあることを発見しました。最初の強制停止の後、Android は 5000 ミリ秒 (5 秒) でアプリケーションを再起動します。これに加えて、サービスが最初の再起動から 60 秒以内に再度強制停止された場合 (2 回目)、Android は次の再起動までの遅延を 4 倍 (つまり、5000 x 4 = 20000ms = 20 秒) 更新します。20 秒後、Android はサービスを再起動します (3 回目)。サービスが 60 秒以内に再度強制停止 (3 回目) された場合、3 回目の再起動後、遅延は 20000 ミリ秒 = 80000 ミリ秒 = 80 秒の 4 倍に更新されます。その結果、サービスが自動再起動の 60 秒以内に強制終了される場合、遅延は指数関数的に増加します (5 秒、20 秒、80 秒、320 秒、1280 秒、.....)。サービスが 60 秒以内に再び強制終了されない場合、遅延タイマーは次の強制停止と再起動のために 5 秒にリセットされます。私の意見では、再起動タイマーが 20 秒を超えるのは不合理です。サービスが実行されているかどうかさえわからない場合、プログラマーはサービスを使用して信頼性の高いアプリを作成する必要がありますか? 自動再起動から 60 秒以内にサービスが強制終了される場合、遅延は指数関数的に増加します (5 秒、20 秒、80 秒、320 秒、1280 秒、......)。サービスが 60 秒以内に再び強制終了されない場合、遅延タイマーは次の強制停止と再起動のために 5 秒にリセットされます。私の意見では、再起動タイマーが 20 秒を超えるのは不合理です。サービスが実行されているかどうかさえわからない場合、プログラマーはサービスを使用して信頼性の高いアプリを作成する必要がありますか? サービスが自動再起動から 60 秒以内に強制終了される場合、遅延は指数関数的に増加します (5 秒、20 秒、80 秒、320 秒、1280 秒、......)。サービスが 60 秒以内に再び強制終了されない場合、遅延タイマーは次の強制停止と再起動のために 5 秒にリセットされます。私の意見では、再起動タイマーが 20 秒を超えるのは不合理です。サービスが実行されているかどうかさえわからない場合、プログラマーはサービスを使用して信頼性の高いアプリを作成する必要がありますか?

既知の解決策と回避策: スタック オーバーフローには、サービスが最初に強制終了されないようにする方法に焦点を当てた回答が既にいくつかあります。それらの中で最も重要なのは、サービスをフォアグラウンドで開始することです。これを行う方法については、こちらを参照してください。これにより、サービスの開始時に通知が発生します。foreGround でサービスを開始すると、サービスが強制終了されることはほとんどありません。サービスから継続的に実行されるスレッドを生成するなど、他の提案された手段がありました (このスレッドは何もする必要はありません)。これにより、スレッドの「重要性」が高まり、サービスが頻繁に強制終了されることはありません。ただし、これによりバッテリーが消耗する可能性があると思います。

私が発見した新しい解決策: この問題を回避する別の方法を発見しました。この方法は、フォアグラウンド サービスやバッテリー ドレイン スレッドを必要としません。インテントが null の場合、onStartCommand でサービスの startService() を呼び出す必要があります (つまり、サービスの作成が以前に START_STICKY を返したと仮定すると、サービスのシステム再起動です)。startService() を呼び出すと、再起動タイマーの遅延は常に 5 秒にリセットされます。以下のサンプル

public class MyService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
    {
        if( null == intent )
        {
            Log.d( "MyServiceTag", "This is a System Restart");
            /* restart the service with startService().
             * This will ensure that the delay between system force-stop and restart  
             * is always 5 seconds
             */
            startService( new Intent( getBaseContext(), MyService.class));
        }

        return START_STICKY;
    }


    @Override
    public void onDestroy()
    {
        Log.d( "MyServiceTag", "In onDestroy");
    }


    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

}

インテントを介してサービスにパラメーターを渡し、START_REDELIVER_INTENT を使用している、より複雑なシナリオがある場合は、「フラグ」を使用して再起動を検出し、startService を呼び出す前にインテントで追加のパラメーターを再作成する必要がある場合があります。 ().

私のために働いた。お役に立てれば。

于 2013-04-26T14:08:58.990 に答える