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_CREATE은 javadoc에 설명 된 것과 같습니다 if the described PendingIntent **does not** already exists, then simply return null(새 것을 만드는 대신)


9
액션 문자열과 함께 인 텐트를 사용해야합니까? new Intent (context, MyClass.class) 클래스를 지정하려고 시도했지만 작동하지 않는 것 같습니다. 알람이 실행 중일 때도 항상 null을 반환합니다.
toc777

5
toc777, manifest.xml의 intent-filter에서 선언 된 액션과 일치하는 문자열 일 필요는 없습니다
Chris Knight

4
크리스, 내 문제를 일으킨 또 다른 문제 였어 위에서 언급 한 의도는 실제로 작동합니다. :)
toc777

41
둘 다 전화를해야합니다 alarmManager.cancel(pendingIntent)pendingIntent.cancel()반환 false로이 솔루션의 순서를.
Kevin Cooper

26
분명하지 않은 경우이 답변의 코드는 보류중인 의도가 알람 관리자에 등록되었는지 확인하지 않습니다. 이 코드는 단순히 PendingIntent가 getBroadcast를 통해 동일한 목표 의도로 생성되었는지 확인합니다. getBroadcast all 이후와 모든 calendar and alarm manager 항목 전에 alarmUp 코드를 실행하여이를 증명할 수 있습니다. true를 반환합니다. 이 사실은 PendingIntent.cancel을 사용하여 값을 false로 되 돌리는 이유를 설명합니다. 엄밀히 말하면, 이것은 질문에 대답하지 않습니다.
bigh_29

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이 제공되지 않습니다.
Henning

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에 등록 된 다음 두 cancel 메소드로 중지 된 경우 위의 'isWorking'은 여전히 ​​유효합니다. PendingIntent가 AlarmManager에서 제거되지 않은 것으로 보이며 인스턴스를 계속 반환합니다. 그러면 알람이 언제 켜지고 꺼 졌는지 효과적으로 알 수 있습니까?
johnDisplayClass

이것은 실제로 완벽하게 작동했습니다. 참고 사항 : setAction ()과 requestCode ()는 모든 getBroadcast ()에서 동일해야하며 장치에서 앱을 제거 할 가치가 있습니다. 그것은 나를 잡았다. 감사합니다
johnDisplayClass

잘 작동합니다. 감사!
Ambran

1
좋은 예이지만 1001을 개인 요청 코드로 사용하지는 않습니다. 예제를보다 명확하게하려면 0입니다.
Chris

1
"상위 답변"등을 사용하지 마십시오. 대신 답변에 대한 링크를 제공하십시오. 답변은 인기도에 따라 페이지의 위치를 ​​변경할 수 있기 때문입니다.
Kathir

44

경보 관리자의 설정 방법에 대한 문서 의이 인용문 을 참고 하십시오 .

예약 된이 의도에 대한 경보가 이미있는 경우 (Intent.filterEquals에 의해 정의 된 두 의도가 동일 함) 경보가 제거되고이 경보로 대체됩니다.

알람 설정이 필요하다는 것을 알고 있다면 이미 존재하는지 여부를 확인하지 않아도됩니다. 앱이 부팅 될 때마다 만들면됩니다. 과거의 알람을 모두 같은 것으로 교체합니다 Intent.

이전에 생성 된 알람에 남아있는 시간을 계산하거나 이러한 알람이 존재하는지 여부를 알아야하는 경우 다른 접근 방법이 필요합니다. 이러한 질문에 답하려면 알람을 만들 때 공유 준비 데이터를 저장하는 것이 좋습니다. 알람이 설정되는 순간, 알람이 울릴 것으로 예상되는 시간 및 반복 기간 (반복 알람을 설정 한 경우)에 시계 타임 스탬프를 저장할 수 있습니다.


2
제 생각에는 이것이 받아 들여지는 대답이어야합니다. OP가 경보를 다시하지 않는 것을 정당화하는 특별한 상황이 없다면
Jose_GD

제 경우에는 알람이 이미 설정되어 있는지 확인하고 새 알람을 만들거나 기존 알람을 재설정하고 싶지 않습니다.
Imran Aslam

2
훌륭한 답변. OP는 왜 이것을 전혀 확인하지 않았습니까? 당신이 할 필요가 없습니다.
Vijay Kumar Kanta

2
이 솔루션에는 많은 루프 홀이 있습니다. 이것은 이전에 생성 된 알람 시간을 무시할 수 있습니다 (t + 24와 같이 시간을 지정해야한다고 말하면됩니다). 알람이 이미 존재하는지 확인하는 것이 더 안정적인 알람입니다
Naga

10

알람이 2 개 있습니다. 이벤트를 식별하기 위해 조치 대신 추가 기능을 사용하려고합니다.

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

문제는 diff extras를 사용하면 의도 (및 경보)가 고유하지 않을 것입니다. 따라서 어떤 알람이 활성화되어 있는지 확인하려면 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);

인 텐트 엑스트라 와이 솔루션을 사용하면 나에게 도움이되었습니다. 한 가지 변경 사항 만 서비스를 사용하고 있으므로 변경했습니다.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이 아닌 값을 반환하지만 알람이 설정되지 않은 경우가 있습니다.
hopia

6

여기에있는 거의 모든 사람이 정답을 제시했지만, 경보가 작동하는 근거에 대해서는 아무도 설명하지 않았습니다.

실제로 여기에서AlarmManager 작동하는 방법에 대해 자세히 배울 수 있습니다 . 그러나 여기에 빠른 대답이 있습니다

당신은 AlarmManager기본적으로 일정이 PendingIntent미래에 언젠가 는 참조하십시오 . 따라서 예약 된 알람을 취소하려면을 취소해야합니다 PendingIntent.

항상 두 가지를 기록해 두십시오. 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

보류중인 의도가있는 경우 alarmanager와 함께 알람이 예약 된 시간을 얻는 방법이 있습니까?
M. Smith

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의 플래그를 업데이트하므로 참이됩니다.

            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.