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


231

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


4
問題を解決した答えを検証するか、独自のソリューションを投稿してください。
Anis

回答:


322

投稿されたコメント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_CREATEjavadocで説明されているものですif the described PendingIntent **does not** already exists, then simply return null(新しいものを作成する代わりに)。


9
アクション文字列だけでインテントを使用する必要がありますか?クラスnew Intent(context、MyClass.class)を指定してみましたが、動作しないようです。アラームが実行中であっても、常にnullを返します。
toc777 2012

5
toc777、それは、manifest.xmlのintent-filterで宣言されたアクションに一致する文字列である必要はありません
Chris Knight

4
クリス、それは私の問題を引き起こしていた別の問題でした。上記の意図は実際に機能します:)
toc777

41
あなたは両方を呼び出す必要がありますことを注意alarmManager.cancel(pendingIntent)してpendingIntent.cancel()リターンfalseに、このソリューションのために。
Kevin Cooper、

26
明らかではない場合、この回答のコードは、保留中のインテントがアラームマネージャーに登録されていることを確認しません。コードは、PendingIntentが同等のターゲットインテントでgetBroadcastを介して作成されたことを単に確認します。これは、getBroadcast allの後、すべてのカレンダーとアラームマネージャーの前にalarmUpコードを実行することで証明できます。trueを返します。この事実は、値をfalseに戻すためにPendingIntent.cancelを実行する必要がある理由を説明しています。厳密に言えば、これは質問の答えにはなりません。
bigh_29 2015

114

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

使用する adb shell dumpsys alarm

アラームが設定されていることと、アラームが発生するタイミングと間隔を知ることができます。また、このアラームが呼び出された回数。


36
実際には、OPに対するプログラムによる回答ではなく、クールなヒントです。知ってとても良い。
JustSomeGuy

2
通常は長いアラームのリストをフィルタリングするためにgrepを追加します。adb shell dumpsys alarm | grep <e.g. package name of your app>新しいWindowsシステムでも動作します(Win10を使用しています)
muetzenflo

3
grepは、PCではなくモバイルデバイスで実行されます。したがって、grepが機能するかどうかは、Android OSによって異なります。古い電話にはgrepが付属していません。
ヘニング

53

レシーバーを使用した実例(トップの答えはアクションのみでした)。

//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(同じ操作、同じインテント-アクション、データ、カテゴリ、コンポーネント、フラグ)を再取得(処理)する場合、それがまだ有効であれば、同じトークンを表すPendingIntentを受け取ります。したがって、cancel()を呼び出して削除できます。

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


1
これで十分かどうかはわかりません。PendingIntentがAlarmManagerに登録され、両方のキャンセルメソッドによって停止された場合、上記の「isWorking」は引き続きtrueになります。PendingIntentはAlarmManagerから削除されていないようで、インスタンスを返し続けます。次に、アラームがいつオン/オフになったかを効果的に知るにはどうすればよいですか?
johnDisplayClass

これは実際には完全に機能しました。注意事項:setAction()とrequestCode()は、すべてのgetBroadcast()で同一である必要があり、デバイスからアプリをアンインストールする価値があります。それは私を見つけました。ありがとう
johnDisplayClass

よく働く。ありがとう!
Ambran 2016

1
良い例ですが、ここではプライベートリクエストコードとして1001を使用しません。例をより明確にするために、ちょうど0。
Chris

1
「トップアンサー」等の使用はご遠慮ください。代わりにアンサーへのリンクを張ってください。回答は人気に基づいてページ上の位置を変更できるためです。
Kathir 2018

44

アラームマネージャーのsetメソッドのドキュメントからのこの引用に注意してください。

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

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

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


2
私の意見では、これは受け入れられる答えであるはずです。OPは詰めがアラーム修正再表示しないように、特別な事情がない限り
Jose_GD

私の場合、アラームが既に設定されているかどうかを確認します。設定されている場合は、新しいアラームを作成したり、既存のアラームをリセットしたりしません。
Imran Aslam 2017

2
素晴らしい答え。なぜOPはこれをまったくチェックしなかったのですか?何もする必要はありません。
Vijay Kumar Kanta 2018年

2
このソリューションには多くのループホールがあり、これは以前に作成されたアラーム時間をオーバーライドする場合があります(t + 24のように時間を指定する必要があるかどうかを言います)。そのため、アプリが起動されるたびに、アラーム時間が常に取得できない状態に進みます。多くのユーザーがトリガーするため、アラームが既に存在するかどうかを確認する方が信頼性が高くなります
Naga

10

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

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

問題は、diffエクストラを使用すると、意図(およびアラーム)が一意にならないことです。どのアラームがアクティブであるかどうかを特定できるように、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);

インテントエクストラとこのソリューションを使用するとうまくいきました。変更点は1つだけです。サービスを使用しているため、次のように変更しました。PendingIntent.getService
Pankaj

8

ちょうど別の解決策を見つけた、それは私のために働くようです

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);
    }

Marshmallowでは、アプリを強制停止した後、getBroadcast()がnull以外を返すことがありますが、アラームは設定されません。
ホピア、

6

ここにいるほとんどの人が正しい答えを出していますが、アラームの仕組みがどのような根拠で説明されているのかはわかりません。

ここでAlarmManager、実際にその動作についてさらに学ぶことができます。しかし、ここに簡単な答えがあります

あなたはAlarmManager基本的にスケジュールPendingIntentを将来的に見ていきます。したがって、スケジュールされたアラームをキャンセルするには、をキャンセルする必要がありますPendingIntent

作成中は常に2つのことに注意してください PendingIntent

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


リクエストコードが識別子である場合、一致するアクションでインテントを渡すことは重要ですか?
Sekula1991、19年

保留中の意図がある場合に、アラームがalarmanagerでスケジュールされた時間を取得する方法はありますか?
M.スミス

4

私は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;)

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


1
    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");

            }

0

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.