PendingIntentとAlarmManagerについて検証してみる

Android

使ってみないとよくわからない機能の一つがPendingIntentですよね。
今回は、アラームなどでよく利用するPendingIntentで、忘れてしまったことやちょっとわかりにくいことが個人的にあったので、記録しておきます。

次のようなサンプルコードを用意します。

 //AlarmTestActivity.java
 public class AlarmTestActivity extends Activity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aram_test);
 
        String type = "ON";
        PendingIntent alarmSender = getPendingIntent(4, type);
 
        // アラーム時間設定
        Calendar cal = Calendar.getInstance();
 
        // 設定した時刻をカレンダーに設定
        cal.set(Calendar.HOUR_OF_DAY, 12);
        cal.set(Calendar.MINUTE, 02);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
 
 
        AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmSender);
        } else {
            am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmSender);
        }
 
 
        // アラーム時間設定 2
        Calendar cal2 = Calendar.getInstance();
 
        // 設定した時刻をカレンダーに設定
        cal2.set(Calendar.HOUR_OF_DAY, 12);
        cal2.set(Calendar.MINUTE, 05);
        cal2.set(Calendar.SECOND, 0);
        cal2.set(Calendar.MILLISECOND, 0);
 
       /* SimpleDateFormat df2 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        Date alarm_day2 = cal2.getTime();
        String alarmDate2 = df2.format(alarm_day2);
        Log.d("AramTestActivity", alarmDate2);*/
 
        AlarmManager am2 = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            am2.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), alarmSender);
        } else {
            am2.set(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), alarmSender);
        }
 
 
    }
 
 
     public PendingIntent getPendingIntent(int i, String type) {
 
        Intent intent = new Intent(this, AlarmReceiver.class);
        intent.putExtra("type", type);
 
        // アラーム時に起動するアプリケーションを登録
        PendingIntent pendingIntent = null;
        if (type.equals("ON")) {
 
            pendingIntent = PendingIntent.getBroadcast(this,
                    10000 + i,
                    intent, PendingIntent.FLAG_UPDATE_CURRENT);
 
        } 
 
        return pendingIntent;
    }
 
 }
 //AlarmReceiver.java
 public class AlarmReceiver extends BroadcastReceiver {
 
    private final static String TAG = "AlarmReceiver"; 
    
    @Override
    public void onReceive(Context context, Intent i) {
 
        try {
            
            Bundle extras = i.getExtras();
            String type = extras.getString("type");
            Log.d(TAG, "AlarmReceiver起動");
            
            if(type != null){
             
                Intent intent = null;
                if(type.equals("ON")){
     
                    intent = new Intent(context, LocationUpdateAlwaysService.class);
    
                }
            
            }
            
        } catch (Exception e) {
            
            Log.d(TAG, "エラー" + e);
        
        }
 
    }
 
 }

12時2分と12時5分にAlarmReceiverが動作しそうですが、しません。
この場合は、5分のやつだけ動作します。
時間を逆にしてみたらどうでしょうか。
先に5分のやつ、次に2分のやつに順序を変更してみます。

       PendingIntent alarmSender = getPendingIntent(4, type);
 
        // アラーム時間設定
        Calendar cal = Calendar.getInstance();
 
        // 設定した時刻をカレンダーに設定
        cal.set(Calendar.HOUR_OF_DAY, 12);
        cal.set(Calendar.MINUTE, 05);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
 
        AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmSender);
        } else {
            am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmSender);
        }
 
       // PendingIntent alarmSender2 = getPendingIntent(4, type);
 
        // アラーム時間設定
        Calendar cal2 = Calendar.getInstance();
 
        // 設定した時刻をカレンダーに設定
        cal2.set(Calendar.HOUR_OF_DAY, 12);
        cal2.set(Calendar.MINUTE, 02);
        cal2.set(Calendar.SECOND, 0);
        cal2.set(Calendar.MILLISECOND, 0);
 
        AlarmManager am2 = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            am2.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), alarmSender);
        } else {
            am2.set(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), alarmSender);
        }

この場合は、2分のやつだけ動作します。

PendingIntentのフラグに

 PendingIntent.FLAG_ONE_SHOT

を設定しても、動作は同じです。
上書き設定された方が動作するわけですね。

       String type = "ON";
        PendingIntent alarmSender = getPendingIntent(4, type);
 
        // アラーム時間設定
        Calendar cal = Calendar.getInstance();
 
        // 設定した時刻をカレンダーに設定
        cal.set(Calendar.HOUR_OF_DAY, 12);
        cal.set(Calendar.MINUTE, 05);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
 
        AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmSender);
        } else {
            am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), alarmSender);
        }
 
        //これが新しいPendingIntent
        PendingIntent alarmSender2 = getPendingIntent(4, type);
 
        Calendar cal2 = Calendar.getInstance();
 
        // 設定した時刻をカレンダーに設定
        cal2.set(Calendar.HOUR_OF_DAY, 12);
        cal2.set(Calendar.MINUTE, 02);
        cal2.set(Calendar.SECOND, 0);
        cal2.set(Calendar.MILLISECOND, 0);
 
        AlarmManager am2 = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            am2.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), alarmSender2);
        } else {
            am2.set(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), alarmSender);
        } 

2番目のアラームは、違うPendingIntentを作成してみます。
PendingIntent alarmSender と PendingIntent alarmSender2 があります。
ただし、リクエストコードは4で一緒です。
これも、2分のものしか動作しません。
同じリクエストコードだと、上書きされちゃうんですね。

リクエストコードを変更します。

 PendingIntent alarmSender2 = getPendingIntent(5, type);

今度は2分のアラームも5分のアラームも動作します。

コメントを残す

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