ひさびさのpostでAlarmManager
久々のPostです。そして、今回は軽めな内容でAlarmManagerを使った実装をしたいと思います。
AlarmManagerとは
Systemが提供するAlarm Serviceを使う事が出来る。Alarm Serviceを使う事によって、deviceがsleep状態にあったとしても将来のある時点でapplicationを起動し、処理を実行することが出来ます。(原文、ここ)
実装の要点は下記です
- AlarmManagerを取得
- Intentを作成
- 上記IntentからPendingIntentを作成
- AlarmManagerにPendingIntentを登録
- 該当のIntentに反応するようにReceiverにIntentFilterを登録
- BroadcastReceiverを拡張したclassでAlarmManagerから発行されたIntentを受信した際の処理を記載
- 必要に応じてAlarmManagerに登録していたIntentをキャンセル(キャンセルしないとActivityが終了してもAlarmManagerは該当のIntentのAlarmを発行し続ける次回Activity起動時は既にPendingIntentが登録されて状態で起動する)
気づいた点をまとめます
- AlarmManager#setRepeating()を使用する場合はflagはPendingIntent.FLAG_ONE_SHOTでは駄目(一回通知されて終了してしまう)
- ELAPSED_REALTIME_WAKEUPは実機がSleep状態でもwakeしてIntentをBroadcastする
- IntentはIntent#filterEquals()で比較されAction, data, type, class, categoryが同じであれば同じIntentと見なされる。extraは比較対象外
んで実装です
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.example" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".AlarmManagerActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name="com.android.example.AlarmReceiver"/> </application> </manifest>
Activity, BroadcastReceiver
package com.android.example; import android.app.Activity; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.os.SystemClock; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; public class AlarmManagerActivity extends Activity { private static final String TAG = "AlarmManagerActivity"; private static final String ACTION_TEXT_UPDATE = "com.android.example.ACTION_TEXT_UPDATE"; private Button mAlarmStartButton; private Button mAlarmStopButton; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mAlarmStartButton = (Button)findViewById(R.id.alarm_start_button); mAlarmStopButton = (Button)findViewById(R.id.alarm_stop_button); mAlarmStartButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Context context = AlarmManagerActivity.this; //AlarmManagerを取得 AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); //PendingIntentを作成 Intent intent = new Intent(); intent.setAction(ACTION_TEXT_UPDATE); //AlarmManager#setRepeating()を使用する場合はflagはPendingIntent.FLAG_ONE_SHOTでは駄目(一回通知されて終了してしまう) PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); //AlarmManagerにPendingIntentを登録 //ELAPSED_REALTIME_WAKEUPは実機がSleep状態でもwakeしてIntentをBroadcastする am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 100, 5000, pendingIntent); } }); mAlarmStopButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Context context = AlarmManagerActivity.this; AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(); intent.setAction(ACTION_TEXT_UPDATE); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); //必要に応じてAlarmManagerに登録していたIntentをキャンセル //キャンセルしないとActivityが終了してもAlarmManagerは該当のIntentのAlarmを発行し続ける //次回Activity起動時は既にPendingIntentが登録されて状態で起動する //IntentはIntent#filterEquals()で比較されAction, data, type, class, categoryが同じであれば同じIntentと見なされる。extraは比較対象外 am.cancel(pendingIntent); } }); //該当のIntentに反応するようにReceiverにIntentFilterを登録 IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_TEXT_UPDATE); registerReceiver(new AlarmReceiver(), filter); } public class AlarmReceiver extends BroadcastReceiver{ //BroadcastReceiverを拡張したclassでAlarmManagerから発行されたIntentを受信した際の処理を記載 @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals(ACTION_TEXT_UPDATE)){ Toast.makeText(context, "onReceive", Toast.LENGTH_SHORT).show(); } } } }
って、こんな感じです。次回もManager系のpostしたいと思います。
HashTag #java, #android, #PendingIntent, #BroadcastReceiver, #AlarmManager, #IntentFilter