programing

AlarmManager에 알람이 이미 설정되어 있는지 확인하는 방법은 무엇입니까?

lastmoon 2023. 9. 4. 20:35
반응형

AlarmManager에 알람이 이미 설정되어 있는지 확인하는 방법은 무엇입니까?

내 앱이 시작되면 특정 알람(알람 관리자를 통해 등록)이 이미 설정되어 실행 중인지 확인하고 싶습니다.구글의 결과는 이것을 할 방법이 없다는 것을 나타내는 것 같습니다.이것이 여전히 맞습니까?새 알람을 만들기 위한 조치를 취하기 전에 사용자에게 알려주기 위해 이 확인을 해야 합니다.

게시된 댓글에 이어 자세한 해결책을 알려드립니다.다음과 같은 보류 중인 의도로 반복 경보를 등록했다고 가정합니다.

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자바독에 설명된 바와 같이,if the described PendingIntent **does not** already exists, then simply return null 것을 ()▁(새

이것이 필요할 수 있는 다른 사람들을 위해, 여기 답이 있습니다.

사용하다adb shell dumpsys alarm

알람이 설정되었으며 알람이 언제 알람과 간격을 설정하는지 알 수 있습니다.또한 이 경보가 호출된 횟수입니다.

수신기를 사용한 작업 예제(가장 높은 답변은 작업뿐임)

//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...");

언급할 가치가 있습니다.

생성 응용 프로그램이 나중에(프로세스) 동일한 종류의 보류 중을 다시 검색하는 경우Intent(동일한 작업, 동일한 작업 - 작업, 데이터, 범주, 구성 요소, 플래그), 보류 중을 수신합니다.여전히 유효한 경우 동일한 토큰을 나타내는 의도이므로 취소()를 호출하여 제거할 수 있습니다.

간단히 말해서, 당신의 보류 중입니다.의도는 동일한 기능(조작 및 의도의 구조)을 가지고 있어야 제어할 수 있습니다.

알람 관리자의 설정 방법에 대한 문서의 다음 인용문을 참고하십시오.

예약된 이 Intent에 대한 알람이 있는 경우(Intent에 의해 정의된 두 개의 intent가 동일).filter Equals)를 선택하면 제거되고 이 파일로 대체됩니다.

알람 설정을 원하는 경우 알람이 이미 존재하는지 여부를 확인할 필요가 없습니다.앱이 부팅될 때마다 만들기만 하면 됩니다.한 " " " "으로합니다.Intent.

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

알람이 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);

방금 다른 해결책을 찾았어요, 저한테 효과가 있는 것 같아요.

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

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

에대실제자알수있다니습아볼세히에 대해 더 배울 수 .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돌아올 것입니다.nullPendingIntent이미 존재하지 않습니다.▁to▁the▁reference다▁if▁returns▁already에 대한 참조를 반환합니다.PendingIntent

저는 단순한 (멍청하든 아니든) bash 스크립트를 만들었는데, 이 스크립트는 adb 쉘에서 긴 부분을 추출하여 타임스탬프로 변환하고 빨간색으로 표시합니다.

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

해보세요 ;)

12 31) 을 , Android 12 (skdk 31) 에 AlarmManager,PendingIntent변경 가능 또는 불변 플래그 없이는 만들 수 없습니다.이 Mutability 플래그가 없으면 응용 프로그램에서 런타임 오류를 발생시킵니다.자세한 내용은 이 설명서를 참조하십시오.다음 코드 스니펫은 Android 12에 대한 애플리케이션을 대상으로 하는 동료들에게 도움이 될 것입니다.

알람을 생성하는 경우:

public static void setupReminderServiceAlarm ( Context context ) {
    Log.d ( TAG, "Trying to setup reminder service alarm" );
    if (!isReminderServiceAlarmSet ( context )) {
        AlarmManager alarmManager = (AlarmManager) context.getApplicationContext ().getSystemService ( Context.ALARM_SERVICE );
        Intent intent = new Intent ( context.getApplicationContext (), ReminderIntentReceiver.class );
        intent.setAction ( REMINDER_INTENT_ACTION );
        PendingIntent pendingIntent;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
            pendingIntent = PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE );
        } else {
            pendingIntent = PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, 0 );
        }
        alarmManager.setRepeating ( AlarmManager.RTC_WAKEUP, getReminderTriggerTime (), REMINDER_INTERVAL, pendingIntent );
        Log.d ( TAG, "Reminder service alarm setup completed" );
    }
}

알람이 이미 설정되어 있는지 확인하는 경우:

private static boolean isReminderServiceAlarmSet ( Context context ) {
    Intent intent = new Intent ( context.getApplicationContext (), ReminderIntentReceiver.class );
    intent.setAction ( REMINDER_INTENT_ACTION );
    boolean isBackupServiceAlarmSet;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_NO_CREATE );
        isBackupServiceAlarmSet = (PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_NO_CREATE ) != null);
    } else {
        PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_NO_CREATE );
        isBackupServiceAlarmSet = (PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_NO_CREATE ) != null);
    }
    Log.d ( TAG, "Reminder service alarm is " + (isBackupServiceAlarmSet ? "" : "not ") + "set already" );
    return isBackupServiceAlarmSet;
}

이전에 설정한 알람을 취소하는 경우:

public static void cancelReminderServiceAlarm ( Context context ) {
    Log.d ( TAG, "Reminder service alarm canceled" );
    AlarmManager alarmManager = (AlarmManager) context.getApplicationContext ().getSystemService ( Context.ALARM_SERVICE );
    Intent intent = new Intent ( context.getApplicationContext (), ReminderIntentReceiver.class );
    intent.setAction ( REMINDER_INTENT_ACTION );
    PendingIntent pendingIntent;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        pendingIntent = PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE );
    } else {
        pendingIntent = PendingIntent.getBroadcast ( context.getApplicationContext (), REMINDER_INTENT_REQUEST_CODE, intent, 0 );
    }
    alarmManager.cancel ( pendingIntent );
    pendingIntent.cancel ();
}

이 답변이 안드로이드 12 / SDK 31+를 대상으로 하는 사람들에게 도움이 되기를 바랍니다.또한 위를 대상으로 하는 알람을 예약하려면 매니페스트에 이 권한을 추가해야 합니다.

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
    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가 Flag of 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");

            }

제 경험으로 볼 때, 안드로이드 최신 버전에서는 서비스를 직접 시작하지 않고 알람 깨우기용 브로드캐스트 메시지만 허용한다고 생각합니다.다음 링크를 참조하십시오. https://developer.android.com/training/scheduling/alarms, :

경보에는 다음과 같은 특성이 있습니다.

  • 설정된 시간 및/또는 간격으로 의도를 발사할 수 있습니다.
  • 브로드캐스트 수신기와 함께 사용하여 서비스를 시작하고 다른 작업을 수행할 수 있습니다.

두 번째 문장에서 가장 중요한 단어는 "접속"입니다.경보가 브로드캐스트용으로 설계되었다는 것은 서비스를 직접 시작하는 것이 아니라는 것을 의미합니다.Pending을 사용하려고 몇 시간 동안 시도했습니다.getService()를 사용하여 의도했지만 다음을 사용하여 보류 중인 의도가 올바르게 작동하는지 확인했음에도 불구하고 실행할 수 없습니다.

pendingIntent.send(0);

"targetSdkVersion 29"의 경우에는 작동하지 않았습니다.[StartCommand()에서 실행되지 않음]:

Intent launchIntent = new Intent(context, MyService.class);
launchIntent.putExtra(Type.KEY, SERVER_QUERY);    
PendingIntent pendingIntent =
                PendingIntent.getService(context, 0, launchIntent, 0);

다음을 사용하여 경보가 실행 중인지 확인할 수 있었습니다.

adb shell dumpsys alarm | grep com.myapp

하지만, 이것은 효과가 있었습니다.

public static class AlarmReceiverWakeup extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(TAG, "onReceive Alarm wakeup");
        startService(context);
    }
}


public static void scheduleAlarmWakeup(Context context) {

    Intent broadcastIntent = new Intent(context, AlarmReceiverWakeup.class);
    broadcastIntent.putExtra(Type.KEY, SERVER_QUERY);    
    PendingIntent pendingIntent =
                    PendingIntent.getBroadcast(context, 0, broadcastIntent, 0);
    AlarmManager alarmManager =
                (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    // NOTE: using System.currentTimeMillis() fails w/ELAPSED_REALTIME_WAKEUP 
    //     use SystemClock.elapsedRealtime() instead
    alarmManager.setRepeating(
                AlarmManager.ELAPSED_REALTIME_WAKEUP,
                SystemClock.elapsedRealtime()+5000,
                AlarmManager.INTERVAL_FIFTEEN_MINUTES/4,
                getAlarmPendingIntent(context)
    );
}

참고로 브로드캐스트 수신기의 AndroidManifest.xml 항목입니다.

<receiver android:name=".ServerQueryService$AlarmReceiverWakeup"
    android:enabled="true">
    <intent-filter>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</receiver>

나는 이것을 할 방법이 없다는 인상을 받고 있지만, 그것은 좋을 것입니다.

Alarm_last_set_time을 어딘가에 기록하고 On_boot_starter BroadcastReceiver를 설정하면 유사한 결과를 얻을 수 있습니다.BOOT_COMPLETED 같은 것.

안드로이드 제트팩 workManager를 사용하여 해결했습니다.

alarmManager에서 알람을 바로 설정하는 대신 workManager에서 트리거 시간(workManager에서 트리거 시간 설정)을 설정하고 해당 작업에 태그를 추가할 수 있는 workManager에서 work를 설정합니다.작업이 트리거될 때 알람을 설정하고 트리거할 수 있습니다.

그리고 당신의 질문에 답하기 위해, 당신은 단순히 다음과 같이 작업에 태그를 추가합니다..addTag("something")그리고 나서 현재 작업 용도를 확인할 때.getWorkInfosByTag("something")

언급URL : https://stackoverflow.com/questions/4556670/how-to-check-if-alarmmanager-already-has-an-alarm-set

반응형