*2016/11/13加筆修正
現在お試し実装中のアプリのメモです。毎週決まった時間に、アラームマネージャを使ってイベントを発生させるときの処理構造になります。推奨される実装かどうかは微妙ですが…調べてたどり着いた着地点でもあります。絵がなくてすみません。
大まなか動作イメージは、以下のようになります。
- メインのActivityで、BroadcastReceiverのインスタンスをアラームマネージャにセットする
- BroadcastReceiverが呼ばれたら、行いたい処理を実施し、再度自分自身をアラームマネージャに登録する(ここが繰り返す)
→ BroadcastReceiverは軽い処理しかできないので、処理をServiceで記述したりするわけですが、ActivityからServiceを呼んでもOKです。というか、BroadcastReceiverを間に挟まなくても動かせることがわかったので、Serviceを呼ぶ方法を推奨します(以下の詳細を御覧ください)。
なお、スマホの再起動後など、再度上記2番を実行するときは、BOOTCOMPLETED機能を使って端末起動時に呼ばれるBroadcastReceiverを定義しておき、その中で2のBroadcastReceiverをアラームマネージャにセットする、という処理を記述すればOKのはずです。
以下、詳細。
以下は、ServiceをAlarmManager経由で呼び出すときの手順です
◯Serviceを定義しておいて、その中に実行したい処理を書いておく
- Activityから(初期起動)
- AlarmManagerのインスタンスを生成(※2)
- AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
- 初回呼び出しまでの時間を計算
- ※1のIntent変数を定義
- 渡したいパラメータがあれば、putExtraなどで入れておく(※3)
- PendingIntentのインスタンスを生成。idは、あとでcancelする可能性がある場合は管理したidを使う(※6)
- ※2を使ってアラームをセットする(※7)
- Build.VERSION.SDK_INT >= 19なら、setExactを使う。
- それ以外は、setを使う。上記条件でも、発火時間が適当でいいときは、setExactを使わなくていい
- am.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pending)
- arg1は、アラームで確実に起こすために必要(らしい)
- arg2は、初回呼び出し時間を計算した結果をcalendarに入れておいたのを呼び出す
- arg3は、Serviceクラスを指定して定義したPendingIntentのインスタンス
- PendingIntent記述例
- PendingIntent pending = PendingIntent.getService(con, 0, intent1, PendingIntent.FLAG_CANCEL_CURRENT);
- arg0 : context
- arg1 : id(複数のアラームを制御する場合、それぞれにuniqなidを用意する)
- arg2 : Serviceのintent
- arg3 : PendingIntentのオプション(詳しくは他のウェブサイトで調べてください)
◯Serviceの定義構造
- public class xxxService extends Service
- onCreateを定義しておくけど、中に処理を書くかどうかはケース・バイ・ケース
- @Override
- public void onCreate(){
- super.onCreate();
- }
- public int onStartCommand(Intent intent, int flags, int startId) に処理を書いていく
- Bundle extras = intent.getExtras();
- String name = extras.getString("name"); などにより、上記Activity ※3 で設定しておいたパラメータを取得する(※5)
- 処理を記述(※4)
- ※4で処理を終えたら、自分自身をあとで呼び出すためのアラーム定義
- Intent alarm_intent = new Intent(context, xxxService.class);
- alarm_intent.putExtra("name", name); などにより、※5で取得したパラメータを再設定する
- 次の実行時間をセットする。以下の例は24時間後(以下のコードは手書きなので誤植あるかもしれません+試してないのでうまく動かないかもしれません)
- Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(System.currentTimeMillis());
- calendar.add(Calendar.HOUR_OF_DAY, 24);
- この設定方法は、このReceiverの呼び出し時間が遅れたとき、遅れた時間+24時間で呼ばれるようになるため、つまり毎日すこしずつ遅れる可能性があるため、「毎日7時」など具体的な時間があるのであれば、それをセットするようにした方がいいです。(具体的な方法は、調べたら書きます)
- PendingIntentのインスタンスを生成 ※6と基本は同じです
- AlarmManagerのインスタンスを生成
- AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
- Androidのバージョンで、呼ぶタスクを分ける↓ ※7
- if(Build.VERSION.SDK_INT >= 19){
- am.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pending);
- }else {
- am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pending);
- }
以下は、BroadcastReceiverをAlarmManager経由で呼び出すときの手順です
◯BroadcastReceiverを定義しておく(※1)
- Activityから(初期起動)
- AlarmManagerのインスタンスを生成(※2)
- AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
- 初回呼び出しまでの時間を計算
- ※1のIntent変数を定義
- 渡したいパラメータがあれば、putExtraなどで入れておく(※3)
- PendingIntentのインスタンスを生成。idは、あとでcancelする可能性がある場合は管理したidを使う(※6)
- ※2を使ってアラームをセットする(※7)
- Build.VERSION.SDK_INT >= 19なら、setExactを使う。
- それ以外は、setを使う。上記条件でも、発火時間が適当でいいときは、setExactを使わなくていい
- am.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pending)
- arg1は、アラームで確実に起こすために必要(らしい)
- arg2は、初回呼び出し時間を計算した結果をcalendarに入れておいたのを呼び出す
- arg3は、
BroadcastReceiverを継承したclassのインスタンス名 BroadcastReceiverクラスを指定して定義したPendingIntentのインスタンス
- PendingIntent記述例
- PendingIntent pending = PendingIntent.getBroadcast(con, 0, intent1, PendingIntent.FLAG_CANCEL_CURRENT);
- arg0 : context
- arg1 : id(複数のアラームを制御する場合、それぞれにuniqなidを用意する)
- arg2 : Serviceのintent
- arg3 : PendingIntentのオプション(詳しくは他のウェブサイトで調べてください)
◯BroadcastReceiverの定義構造
- public class xxxReceiver extends BroadcastReceiverにonReceiveを定義してその中に定義
- public void onReceive(Context context, Intent intent)
- Bundle extras = intent.getExtras();
- String name = extras.getString("name"); などにより、上記Activity ※3 で設定しておいたパラメータを取得する(※5)
- TTSで定期的にしゃべらせたいので、それをServiceクラスで実行するため、Serviceを用意する。簡単な処理しかしないなら、ここでServiceを呼ぶ必要はない(※4)
- Intent service = new Intent(context, xxxService.class); //xxxService.javaは自分で定義しておく
- service.putExtra("name", name); などにより、Bundleで受け取ったパラメータをServiceへ渡す準備
- context.startService(service); でService実行
- ※4で処理を終えたら、自分自身をあとで呼び出すためのアラーム定義
- Intent alarm_intent = new Intent(context, xxxReceiver.class);
- alarm_intent.putExtra("name", name); などにより、※5で取得したパラメータを再設定する
- 次の実行時間をセットする。以下の例は24時間後(以下のコードは手書きなので誤植あるかもしれません+試してないのでうまく動かないかもしれません)
- Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(System.currentTimeMillis());
- calendar.add(Calendar.HOUR_OF_DAY, 24);
- この設定方法は、このReceiverの呼び出し時間が遅れたとき、遅れた時間+24時間で呼ばれるようになるため、つまり毎日すこしずつ遅れる可能性があるため、「毎日7時」など具体的な時間があるのであれば、それをセットするようにした方がいいです。(具体的な方法は、調べたら書きます)
- PendingIntentのインスタンスを生成 ※6と基本は同じです
- AlarmManagerのインスタンスを生成
- AlarmManager am = (AlarmManager) context.getSystemService(ALARM_SERVICE);
- Androidのバージョンで、呼ぶタスクを分ける↓ ※7
- if(Build.VERSION.SDK_INT >= 19){
- am.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pending);
- }else {
- am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pending);
- }