Edited at

アラームの作り方

More than 3 years have passed since last update.

これが正しい方法かどうかわかりませんが、アラームとして機能したのでメモ

Androidでアラームを鳴らすためには、


  1. アラーム時に起動するサービスをPendingIntentを使って指定する

  2. 指定されたタイミングで起動したサービスからsendBroadcastを利用してレシーバーを起こす

  3. 起こされたレシーバーからアラーム時に起動するActivityをIntentによって指定、起動

というプロセスでいけるようです。

めんどくさいですが。

サービスとレシーバーを利用するためには権限が必要なため、Manifestに記載する

必要な部分のみ書いています。


AndroidManifest.xml


<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />

<application>
<!-- MainActivityなど -->
<receiver android:name="AlarmReceiver" >
<intent-filter>
<action android:name="MyAlarmAction"></action>
</intent-filter>
</receiver>

<service android:name="MyAlarmService" ></service>

<activity android:name="AlarmNotificationActivity" ></activity>
</application>


actionにMyAlarmActionというものをセットしていますが、

これはサービスからレシーバーを起動する際に利用する識別子のようなものです。多分。

アラームの設定自体を行うMyAlarmManager.javaは以下の通り


MyAlarmManager.java

public class MyAlarmManager {

Context c;
AlarmManager am;
private PendingIntent mAlarmSender;

private static final String TAG = MyAlarmManager.class.getSimpleName();

public MyAlarmManager(Context c){
// 初期化
this.c = c;
am = (AlarmManager)c.getSystemService(Context.ALARM_SERVICE);
Log.v(TAG,"初期化完了");
}

public void addAlarm(int alarmHour, int alarmMinute){
// アラームを設定する
mAlarmSender = this.getPendingIntent();

// アラーム時間設定
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
// 設定した時刻をカレンダーに設定
cal.set(Calendar.HOUR_OF_DAY, alarmHour);
cal.set(Calendar.MINUTE, alarmMinute);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);

// 過去だったら明日にする
if(cal.getTimeInMillis() < System.currentTimeMillis()){
cal.add(Calendar.DAY_OF_YEAR, 1);
}
Toast.makeText(c, String.format("%02d時%02d分に起こします", alarmHour, alarmMinute), Toast.LENGTH_LONG).show();

am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), mAlarmSender);
Log.v(TAG, cal.getTimeInMillis()+"ms");
Log.v(TAG, "アラームセット完了");
}

public void stopAlarm() {
// アラームのキャンセル
Log.d(TAG, "stopAlarm()");
am.cancel(mAlarmSender);
spm.updateToRevival();
}

private PendingIntent getPendingIntent() {
// アラーム時に起動するアプリケーションを登録
Intent intent = new Intent(c, MyAlarmService.class);
PendingIntent pendingIntent = PendingIntent.getService(c, PendingIntent.FLAG_ONE_SHOT, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
}


PendingIntentのFLAGについてはhttp://y-anz-m.blogspot.jp/2011/07/androidappwidget-pendingintent-putextra.htmlが詳しいです。

アラームを更新するのか、あるいは前のままにするのか等、用途に合わせて設定して下さい。

getPendingIntent()で定義しているように、PendingIntent.getServiceで呼び出すサービスを指定します。

MyAlarmManagerによって、アラームの時刻を設定したいActivityなどからaddAlarm(hour, minute)で簡単にアラームをセットできます。

次にサービスを見ます。


MyAlarmService.java

public class MyAlarmService extends Service {

private static final String TAG = MyAlarmService.class.getSimpleName();

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onCreate() {
Thread thr = new Thread(null, mTask, "MyAlarmServiceThread");
thr.start();
Log.v(TAG,"スレッド開始");
}
// アラーム用サービス
Runnable mTask = new Runnable() {
public void run() {
// アラームを受け取るActivityを指定
Intent alarmBroadcast = new Intent();
// ここでActionをセットする(Manifestに書いたものと同じであれば何でもよい)
alarmBroadcast.setAction("MyAlarmAction");
// レシーバーへ渡す
sendBroadcast(alarmBroadcast);
// 役目を終えたサービスを止める
MyAlarmService.this.stopSelf();
Log.v(TAG,"サービス停止");
}
};
}


サービスからのBroadCastなIntentを受け取るレシーバー


AlarmReceiver.java

public class AlarmReceiver extends BroadcastReceiver {  

@Override
public void onReceive(Context context, Intent intent) {
// アラームを受け取って起動するActivityを指定、起動
Intent notification = new Intent(context, AlarmNortificationActivity.class);
// 画面起動に必要
notification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(notification);
}
}


だんだんコードが減ってきて、言うことが無くなってきてます。

AlarmReceiverによって起こされるActivity


AlarmNotification.java

public class AlarmNortificationActivity extends Activity {

private MediaPlayer mp;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.alarm_notification);

// スクリーンロックを解除する
// 権限が必要
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

Toast.makeText(this, "アラーム!", Toast.LENGTH_SHORT).show();

}

@Override
public void onStart() {
super.onStart();
Toast.makeText(getApplicationContext(), "アラームスタート!", Toast.LENGTH_LONG).show();
// 音を鳴らす
if (mp == null)
// resのrawディレクトリにtest.mp3を置いてある
mp = MediaPlayer.create(this, R.raw.test);
mp.start();
}

@Override
public void onDestroy() {
super.onDestroy();
stopAndRelaese();
}

private void stopAndRelaese() {
if (mp != null) {
mp.stop();
mp.release();
}
}

@Override
protected void onResume() {
super.onResume();
alarmNowText = (TextView) findViewById(R.id.alarm_now_time);
handler.sendEmptyMessage(WHAT);
// mam.stopAlarm();
}
}


これでalarm_notification.xmlが表示され、Toastが出るはずです。

意外とめんどくさいアラームのメモでした。

アラームを設定する際のベストプラクティスがよくわかっていないので、アドバイス頂けると嬉しいです。