51

私のアプリケーションには、10 分ごとに実行されるように設計された Service があります。基本的に、サーバーをチェックして、すべてが適切に実行されているかどうかを確認し、問題があればユーザーに通知します。このアプリケーションは、社内で使用するために作成しました。

同僚が長い週末にアプリケーションを使用したところ、デバイスがスリープ状態になったときにチェックが実行されていないことに気付きました。stopService()コードを明示的に呼び出すまで、サービスはバックグラウンドで実行され続けるはずだという印象を受けました。

最終的に、私の目標は、ユーザーがアプリケーションのオフ ボタンを押すか、プロセスを強制終了するまで、サービスを実行することです。

WakeLock画面がオフにならないようにするためのものと呼ばれるものについて聞いたことがありますが、これは私が望んでいるものではありません。次に、部分的な WakeLockと呼ばれる別のことを聞きました。これは、デバイスがスリープ状態でも CPU を実行し続けます。後者は、私が必要としているものに近いように聞こえます。

この WakeLock を取得するにはどうすればよいですか? また、いつ解放する必要がありますか? また、これを回避する他の方法はありますか?

4

3 に答える 3

61

注: この投稿は更新されJobScheduler、Android Lollipop リリースの API が含まれるようになりました。以下はまだ実行可能な方法ですが、Android Lollipop 以降をターゲットにしている場合は非推奨と見なすことができます。JobScheduler代替案については、後半を参照してください。

反復タスクを実行する 1 つの方法は次のとおりです。

  • クラスを作成するAlarmReceiver

    public class AlarmReceiver extends BroadcastReceiver 
    {
        @Override
        public void onReceive(Context context, Intent intent) 
        {
            Intent myService = new Intent(context, YourService.class);
            context.startService(myService);
        }
    }
    

    あなたのサービスでYourServiceあることで;-)

タスクにウェイク ロックが必要な場合は、から拡張することをお勧めしWakefulBroadcastReceiverます。WAKE_LOCKこの場合、マニフェストに許可を追加することを忘れないでください!

  • 保留中のインテントを作成する

定期的なポーリングを開始するには、アクティビティで次のコードを実行します。

Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class);
//myAlarm.putExtra("project_id", project_id); //Put Extra if needed
PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
//updateTime.setWhatever(0);    //set time to start first occurence of alarm 
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, recurringAlarm); //you can modify the interval of course

このコードは、alarmおよび キャンセル可能 をセットアップしpendingIntentます。はalarmManagerジョブをrecurringAlarm毎日 (3 番目の引数) 繰り返すように取得しますが、正確ではないため、CPU はほぼ間隔の後にウェイクアップしますが、正確ではありません (OS に最適な時間を選択させ、バッテリーの消耗を減らします)。アラーム (およびサービス) が最初に開始されるのは、あなたが選択した時間ですupdateTime

  • 最後になりましたが、繰り返し発生するアラームを停止する方法は次のとおりです。

    Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class);
    //myAlarm.putExtra("project_id",project_id); //put the SAME extras
    PendingIntent recurringAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager alarms = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    alarms.cancel(recurringAlarm);
    

このコードは、(おそらく) 既存のアラームのコピーを作成し、alarmManagerその種類のすべてのアラームをキャンセルするように に指示します。

  • もちろん、次のようにすることもありますManifest

これらの2行を含めます

  < receiver android:name=".AlarmReceiver"></receiver>
  < service android:name=".YourService"></service>

-タグ内< application>。これがないと、システムはサービスの繰り返しアラームの開始を受け入れません。


Android Lollipopのリリース以降、このタスクをエレガントに解決する新しい方法があります。これにより、ネットワーク状態などの特定の基準が満たされた場合にのみアクションを実行することも容易になります。

// wrap your stuff in a componentName
ComponentName mServiceComponent = new ComponentName(context, MyJobService.class);
// set up conditions for the job
JobInfo task = JobInfo.Builder(mJobId, mServiceComponent)
   .setPeriodic(mIntervalMillis)
   .setRequiresCharging(true) // default is "false"
   .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED) // Parameter may be "ANY", "NONE" (=default) or "UNMETERED"
   .build();
// inform the system of the job
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(task);

で期限を指定することもできますsetOverrideDeadline(maxExecutionDelayMillis)

このようなタスクを取り除くには、jobScheduler.cancel(mJobId);またはを呼び出すだけjobScheduler.cancelAll();です。

于 2012-01-03T14:30:29.760 に答える
5

このアプリケーションを最初からサーバー側コンポーネントを使用して構築し (そうです、監視も必要です!)、プッシュ通知を送信する場合、ポーリングは決して信頼できるソリューションではありません。

于 2012-01-03T14:05:34.217 に答える