web-dev-qa-db-ja.com

AlarmManagerにすでにアラームが設定されているかどうかを確認する方法は?

アプリの起動時に、特定のアラーム(AlarmManagerを介して登録された)が既に設定され実行されているかどうかを確認する必要があります。グーグルからの結果は、これを行う方法がないことを示しているようです。これはまだ正しいですか?新しいアラームを作成するためのアクションが実行される前にユーザーにアドバイスするために、このチェックを行う必要があります。

216
ron

投稿されたコメントronをフォローアップすると、詳細なソリューションがあります。次のような保留中の意図を持つ繰り返しアラームを登録したとします。

Intent intent = new Intent("com.my.package.MY_UNIQUE_ACTION");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, 
                                      intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.MINUTE, 1);

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60, pendingIntent);

アクティブかどうかを確認する方法は次のとおりです。

boolean alarmUp = (PendingIntent.getBroadcast(context, 0, 
        new Intent("com.my.package.MY_UNIQUE_ACTION"), 
        PendingIntent.FLAG_NO_CREATE) != null);

if (alarmUp)
{
    Log.d("myTag", "Alarm is already active");
}

ここで重要なのはFLAG_NO_CREATEです。これはjavadocで説明されているように:if the described PendingIntent **does not** already exists, then simply return null(新しいものを作成する代わりに)

308
Chris Knight

これを必要とする他の人のために、ここに答えがあります。

adb Shell dumpsys alarmを使用

アラームが設定され、いつアラームが鳴り、間隔が空くのかを知ることができます。また、このアラームが呼び出された回数。

109
Jack Feng

レシーバーを使用した作業例(一番の答えはアクションだけでした)。

//starting
AlarmManager alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getActivity(), MyReceiver.class);
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//my custom string action name
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);//used unique ID as 1001
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), aroundInterval, pendingIntent);//first start will start asap

//and stopping
Intent intent = new Intent(getActivity(), MyReceiver.class);//the same as up
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//the same as up
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);//the same as up
alarmManager.cancel(pendingIntent);//important
pendingIntent.cancel();//important

//checking if alarm is working with pendingIntent
Intent intent = new Intent(getActivity(), MyReceiver.class);//the same as up
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//the same as up
boolean isWorking = (PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_NO_CREATE) != null);//just changed the flag
Log.d(TAG, "alarm is " + (isWorking ? "" : "not") + " working...");

言及する価値があります:

作成アプリケーションが後で(プロセス)同じ種類のPendingIntent(同じoperation、同じIntent's-アクション、データ、カテゴリ、コンポーネント、フラグ)を再取得すると、同じトークンを表すPendingIntentがまだ有効である場合は、それをキャンセルするためにcancel()を呼び出すことができます。

つまり、PendingIntentを制御するには、同じ機能(操作とインテントの構造)が必要です。

48
deadfish

この引用符 Alarm Managerのsetメソッドのドキュメントから:

スケジュールされたこのIntentのアラームが既にある場合(Intent.filterEqualsで定義されている2つのインテントが等しい場合)、それは削除され、このインテントに置き換えられます。

アラームを設定する必要があることがわかっている場合は、アラームが既に存在するかどうかを確認する必要はありません。アプリを起動するたびに作成してください。過去のアラームを同じIntentに置き換えます。

以前に作成したアラームの残り時間を計算する場合、またはそのようなアラームが存在するかどうかを本当に知る必要がある場合は、別のアプローチが必要です。これらの質問に答えるには、アラームを作成するときに共有設定データを保存することを検討してください。アラームが設定された瞬間のクロックタイムスタンプ、アラームがオフになると予想される時間、および繰り返し期間(繰り返しアラームを設定する場合)を保存できます。

41
bigh_29

2つのアラームがあります。イベントを識別するために、アクションの代わりにエクストラ付きのインテントを使用しています:

Intent i = new Intent(context, AppReciever.class);
i.putExtra("timer", "timer1");

問題は、差分エクストラではインテント(およびアラーム)が一意にならないことです。したがって、どのアラームがアクティブであるかを識別できるようにするには、diff requestCode- sを定義する必要がありました。

boolean alarmUp = (PendingIntent.getBroadcast(context, MyApp.TIMER_1, i, 
                    PendingIntent.FLAG_NO_CREATE) != null);

アラームの作成方法は次のとおりです。

public static final int TIMER_1 = 1;
public static final int TIMER_2 = 2;

PendingIntent pending = PendingIntent.getBroadcast(context, TIMER_1, i,
            PendingIntent.FLAG_CANCEL_CURRENT);
setInexactRepeating(AlarmManager.RTC_WAKEUP,
            cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pending);
pending = PendingIntent.getBroadcast(context, TIMER_2, i,
            PendingIntent.FLAG_CANCEL_CURRENT);
setInexactRepeating(AlarmManager.RTC_WAKEUP,
            cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pending);
10
HiB

別の解決策を見つけたが、それは私にとってはうまくいくようだ

Intent myIntent = new Intent(MainActivity.this, MyReceiver.class);

boolean isWorking = (PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, PendingIntent.FLAG_NO_CREATE) != null);
if (isWorking) {Log.d("alarm", "is working");} else {Log.d("alarm", "is not working");}

if(!isWorking) {
    pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent,    PendingIntent.FLAG_UPDATE_CURRENT);
    alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    int timeNotif = 5 * 60 * 1000;//time in ms, 7*24*60*60*1000 for 1 week
    Log.d("Notif", "Notification every (ms): " + timeNotif);
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), timeNotif, pendingIntent);
    }
7
user3856297

ここにいるほとんどの人が正しい答えを出しましたが、アラームが機能する理由については誰も説明していません

AlarmManagerとその動作 here の詳細を実際に学ぶことができます。しかし、ここに簡単な答えがあります

AlarmManagerは基本的に、将来のある時点でPendingIntentをスケジュールします。そのため、スケジュールされたアラームをキャンセルするには、PendingIntentをキャンセルする必要があります。

PendingIntentを作成するときは、常に2つのことに注意してください

PendingIntent.getBroadcast(context,REQUEST_CODE,intent, PendingIntent.FLAG_UPDATE_CURRENT);
  • 要求コード-一意の識別子として機能
  • フラグ-PendingIntentの動作を定義します

アラームが既にスケジュールされているかどうかを確認するか、アラームをキャンセルするには、同じPendingIntentにアクセスする必要があります。これは、同じリクエストコードを使用し、以下に示すようにFLAG_NO_CREATEを使用する場合に実行できます

PendingIntent pendingIntent=PendingIntent.getBroadcast(this,REQUEST_CODE,intent,PendingIntent.FLAG_NO_CREATE);

if (pendingIntent!=null)
   alarmManager.cancel(pendingIntent);

FLAG_NO_CREATEでは、nullがまだ存在しない場合はPendingIntentを返します。既に存在する場合、既存のPendingIntentへの参照を返します

3
IrshadKumail

Adbシェルからlongを抽出し、それらをタイムスタンプに変換して赤で表示する単純な(愚かな、または愚かな)bashスクリプトを作成しました。

echo "Please set a search filter"
read search

adb Shell dumpsys alarm | grep $search | (while read i; do echo $i; _DT=$(echo $i | grep -Eo 'when\s+([0-9]{10})' | tr -d '[[:alpha:][:space:]]'); if [ $_DT ]; then echo -e "\e[31m$(date -d @$_DT)\e[0m"; fi; done;)

それを試してみてください ;)

3
Jan Ni
    Intent intent = new Intent("com.my.package.MY_UNIQUE_ACTION");
            PendingIntent pendingIntent = PendingIntent.getBroadcast(
                    sqlitewraper.context, 0, intent,
                    PendingIntent.FLAG_NO_CREATE);

FLAG_NO_CREATEは保留インテントを作成しないため、ブール値falseを提供します。

            boolean alarmUp = (PendingIntent.getBroadcast(sqlitewraper.context, 0,
                    new Intent("com.my.package.MY_UNIQUE_ACTION"),
                    PendingIntent.FLAG_NO_CREATE) != null);

            if (alarmUp) {
                System.out.print("k");

            }

            AlarmManager alarmManager = (AlarmManager) sqlitewraper.context
                    .getSystemService(Context.ALARM_SERVICE);
            alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
                    System.currentTimeMillis(), 1000 * 60, pendingIntent);

AlarmManagerがPending Intentの値を確認すると、AlarmManagerがPending Intentのフラグを更新するため、trueになります。

            boolean alarmUp1 = (PendingIntent.getBroadcast(sqlitewraper.context, 0,
                    new Intent("com.my.package.MY_UNIQUE_ACTION"),
                    PendingIntent.FLAG_UPDATE_CURRENT) != null);
            if (alarmUp1) {
                System.out.print("k");

            }
1
MIkka Marmik

これを行う方法はないという印象の下で、私はいいでしょう。

Alarm_last_set_timeをどこかに記録し、On_boot_starter BroadcastReciever:BOOT_COMPLETEDを使用することで、同様の結果を得ることができます。

0
Stephen