ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Android/Java] 알림, 특정주기 알림, 반복 알람 만들기
    Android 2020. 10. 4. 02:59

     

    알림 참고 

    developer.android.com/guide/topics/ui/notifiers/notifications?hl=ko

     

    반복 알람 예약 참고

    developer.android.com/training/scheduling/alarms

     

     

     

    알림 알람 차이를 이렇게 이해하고 글을 썼다 

    알림 : 알리는 행위 자체

    알람 : 설정된 알림 

     


    안드로이드 알림 개요


     

    스마트폰 알림 요소

    - 상대표시줄 알림

    - 알림창의 알림

    - 잠금화면 알림(Android 5.0, API 레벨 21부터)

    - 헤드업 알림(Android 5.0, API 레벨 21부터)

    - 앱 아이콘 뱃지 알림(Android 8.0, API 레벨26 부터)

     

    알림에 사용자가 적절히 반응할 수 있는 액티브 요소를 넣는것이 좋다

    알림 호환성에 대한 내용은 참고링크 맨 밑에서 확인가능

     

     

     

     

     


    알림 만들기 


     

    NotificationCompat 클래스를 사용하면 알아서 API를 호환해준다

     

     

    알람 설정

    NotificationCompat.Builder 객체를 사용해 알림 콘텐츠와 채널을 설정해야한다. 

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setSmallIcon(R.drawable.notification_icon)     #작은 아이콘
                .setContentTitle(textTitle)	                   #제목
                .setContentText(textContent)                  #본문
                .setPriority(NotificationCompat.PRIORITY_DEFAULT);   #알림 우선순위 설정
        

     

    생성자의 경우 채널ID 제공

    채널이란 Android 8.0(API 레벨26) 이상에서 호환성 유지를 위해 필요. 이전 버전에서는 상관X

     

     

    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(NOTIFICATION_ID, builder.build())

     

    ID가 같으면 같은 알람으로 인식해서 알람창에 여러개 안뜨고 하나로 덮어짐 

     

     


    반복 알람 예약 AlarmManager


    앱이 사용되지 않을때도 시간기반 알림 실행하기

     

    AlarmManager 클래스 기반

     

    알람 특징

    - 지정된 시간 또는 정해진 간격으로 인텐트 실행

    - Broadcast receiver와 함께 알람을 사용하여 서비스를 시작하고 다른작업을 실행

    - 앱 외부에서 작동하므로, 알림을 사용하면 앱이 실행중이 아니거나 기기가 대기중일때도 이벤트나 작업 트리거가능

     

     

    반복 알람 특성

    - 알람 유형 (밑에 설명)

    - 트리거 시간. 지정된 시간이 과거이면 알람은 즉시 트리거됨

    - 알람 간격. ex)하루에 한번, 매 시간, 5분 마다

    - 알람이 트리거 되면 실행되는 대기 중인 인텐트. 동일한 인텐트를 사용하는 새 알람을 설정하면 원래 알람을 대체함

     

     

     

    반복 알람 설정

        AlarmManager alarmManager =
            (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        PendingIntent pendingIntent =
            PendingIntent.getService(context, requestId, intent,
                                        PendingIntent.FLAG_NO_CREATE);
        if (pendingIntent != null && alarmManager != null) {
          alarmManager.cancel(pendingIntent);
        }
        

     

    PendingIntent를 취소하려면 FLAG_NO_CREATE를 PendingIntent.getService()에 전달하여 인텐트의 인스턴스(있는 경우)를 가져온 다음 그 인텐트를 AlarmManger.cancel()에 전달

     

    PendingIntent가 FLAG_ONE_SHOT으로 생성된 경우 취소할 수 없음

     

     

     

    알람 유형

    크게 2가지 기준으로 나뉨

    1. 기기 부팅 후 실제 경과시간 

    2. 실시간 시계(RTC) 

     

     

    둘다 화면이 꺼져 있을때 기기에서 CPU 절전 모드르 해제하는 wakeup 버전을 제공

    ※ wakeup 버전의 알람 유형을 사용하지 않으면 기기가 다음에켜질때 모든 반복 알람이 실행됨

     

    특정 간격(ex 30분마다) 알람을 실행한다면, 실제 경과시간 유형

    하루 중 특정 시간에 실행되면 시간 기반의 실시간 시계 유형

     

     

    • 유형 목록

    - ELAPSSED_REALTIME : 기기 부팅 후 경과한 시간을 기반으로 대기 인텐트 실행. 기기 절전모드 해제X

    경과시간은 기기가 대기상태였던 시간을 포함함

    - ELAPSED_REATIME_WAKEUP : 기기 부팅 후 지정된 시간이 경과하면 기기 절전을 해제하고 대기중인 인텐트 실행

    - RTC : 지정된 시간에 대기중인 인텐트 실행. 기기의 절전모드는 해제X

    - RTC_WAKEUP : 지정된 시간에 기기의 절전 모드를 해제하여 대기 중인 인텐트 실행

     

     

    • 실제 경과시간 알람 예시

    - 알람 설정한 후 30분 마다 기기 절전모드를 해제하여 알람 실행

        // Hopefully your alarm will have a lower frequency than this!
        alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
                AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);
        

     

     

    - 1분 후 기기의 절전모드를 해제하여 일회성 알람을 실행

        private AlarmManager alarmMgr;
        private PendingIntent alarmIntent;
        ...
        alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(context, AlarmReceiver.class);
        alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
    
        alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                SystemClock.elapsedRealtime() +
                60 * 1000, alarmIntent);
        

     

     

    • 실시간 시계 알람 예시

    - 오후 2시에 기기절전 모드를 해제하여 알람 실행, 하루 한번 동일한 시간에 반복

        // Set the alarm to start at approximately 2:00 p.m.
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.set(Calendar.HOUR_OF_DAY, 14);
    
        // With setInexactRepeating(), you have to use one of the AlarmManager interval
        // constants--in this case, AlarmManager.INTERVAL_DAY.
        alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
                AlarmManager.INTERVAL_DAY, alarmIntent);
        

     

    - 정확히 오전 8시30분에 기기 절전모드 해제하여 알람 실행, 그 후 20분 마다 반복

        private AlarmManager alarmMgr;
        private PendingIntent alarmIntent;
        ...
        alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(context, AlarmReceiver.class);
        alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
    
        // Set the alarm to start at 8:30 a.m.
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.set(Calendar.HOUR_OF_DAY, 8);
        calendar.set(Calendar.MINUTE, 30);
    
        // setRepeating() lets you specify a precise custom interval--in this case,
        // 20 minutes.
        alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
                1000 * 60 * 20, alarmIntent);
        

     

     

     

    • 알람 취소

    알람 관리자의 cancel()을 호출하여 취소할 PendingIntent를 전달

        // If the alarm has been set, cancel it.
        if (alarmMgr!= null) {
            alarmMgr.cancel(alarmIntent);
        }
        

     

     

     


    기기가 다시 시작되어도 알람 실행하기 


     

    기기를 종료하면 설정된 모든 알람이 취소됨. 그러므로 기기가 재부팅 될 때 

    자동으로 반복 알람이 다시 시작하도록 기능추가

     

    1. 안드로이드 매니페스트에 RECEIVE_BOOT_COMPLETED 권한 설정

    AndroidManifest.xml 파일에 다음 항목 추가

        <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

    이 권한을 사용하면 시스템 부팅이 끝난 후 해당 앱은 브로드캐스팅되는 ACTION_BOOT_COMPLETED를 받음

    그 후 브로드캐스트 수신기 설정하면됨

     

    2. BroadcastReceiver를 구현하여 브로드캐스트 받기

        public class SampleBootReceiver extends BroadcastReceiver {
    
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
                    // Set the alarm here.
                }
            }
        }
        

     

     

    3. AndroidManifest.xml 에서 ACTION_BOOT_COMPLETED 작업을 필터링 하는 인텐트 필터 및 Broadcast 수신기 추가

    <receiver android:name=".SampleBootReceiver"
                android:enabled="false">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"></action>
            </intent-filter>
        </receiver>

    android:enabled=false 이므로 특정 명시적 인텐트만 받는다. ( 인텐트 및 브로드캐스트 참고)

    이렇게 하면 부팅 수신기가 불필요하게 호출되는 것을 방지

     

    - 수신기 사용 예시(사용자가 알람을 설정한 경우)

        ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
        PackageManager pm = context.getPackageManager();
    
        pm.setComponentEnabledSetting(receiver,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);
        

    사용자가 기기를 재부팅해도 수신기는 사용할 수 있는 상태다. 

    수신기를 프로그래매틱 방식으로 사용하면 재부팅해도 manifest 설정에 의해 재정의된다.

    수신기는 앱이 중지할때까지 사용할 수 있는 상태로 남아있는다. 

     

    다음과 같이 수신기를 중지할 수 있다.(ex 사용자가 알람을 취소한 경우)

        ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
        PackageManager pm = context.getPackageManager();
    
        pm.setComponentEnabledSetting(receiver,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
        

     

     

     

     

    • 잠자기 및 앱 대기 상태에서도 알람 실행하기 

    Android 6.0(API 레벨 23) 에서 도입됨

    해당 상태에서 알람을 실행하려면

    setAndAllowWhileIdel() 또는 setExactAndAllowWhileIdle() 사용

     

     

     

     

    • 알람 권장사항

    - 필요 이상으로 트리거 시간을 정밀 설정하지 말것

    SetRepeating() 대신 setInexacRepeating() 사용

     

Designed by Tistory.