Android の AlarmManager で onReceive が呼ばれない



Android の AlarmManager での処理を実装していたときにハマったので注意点を書いておきます。

異なる時間に実行する複数のアラームを同時にセットする

今回は定期的ではなく、いくつかの時刻で少しずつ異なる処理をさせたかったのですが、それを一度にセットしようと考えていました。内容が異なる Intent をそれぞれセットした pendingIntent を複数 AlarmManager に送るということをしていました。

しかし、指定した時間が来ても BroadcastReceiver の onReceive が呼ばれません。単体のアラームだと呼ばれますが、複数にすると呼ばれません。

AlarmManager の状態を確認すると複数のアラームがセットされて見える

AlarmManager の状態を取得するには、開発環境から以下のようにコマンドを実行します。

アラームマネージャーの状態がダンプされた alarm.txt を確認すると、複数のアラームがセットされているように見えます。

しかし、あとでわかったことですが、実際には最後のアラームだけが有効になっていました。

原因は単純なことですが、Intent を PendungIntent に渡すときに以下のようにして第4引数に PendingIntent.FLAG_CANCEL_CURRENT を指定していました。

この状態だと、次の PendingIntent が AlarmManager に渡されたときに、前ものと同一だと判断されてキャンセルされていました。そのため、一番最後に追加した(かなり時間が先の)予定だけが有効になった状態になっていたようです。しかし、キャンセルされているにもかかわらず AlarmManager の状態ダンプではすべて実行されているよう見えてしまいます(ここでハマりました)……。

第4引数に PendingIntent.FLAG_UPDATE_CURRENT を指定してみると、1つだけ有効になりました。しかし複数を事前にセットしてしまうと、上書きされていくので、最後のものだけが残る感じです。これはこれで便利なのですが。

解決策

複数の予定を AlarmManager に登録することはあきらめて、直近で呼び出したいもの1つだけを登録しました。第4引数には PendingIntent.FLAG_ONE_SHOT を指定して呼び出しました。そしてレシーバーの onReceive で必要な処理をしたあと、改めて次のアラームをセットするようにしました。

今回は単純な繰り返しアラームではないので、こちらの方が柔軟に対応できました。Intent の使っていないパラメータをセットして別のアラームとして認識させる方法もありますが、Android のアラームは時間がずれることがあり、定期的にセットし直さないといけないという理由もあり、今回は1件ずつ登録するようにしました。

参考サイト


コメントを残す

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