Help us understand the problem. What is going on with this article?

アラームの作り方

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が出るはずです。

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

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした