Computer >> 컴퓨터 >  >> 프로그래밍 >> Android

Android에서 특정 날짜와 시간에 알림이 울리도록 설정하는 방법

이 튜토리얼에서는 AlarmManagerTimePickerDialog를 활용하여 Android 앱에서 사용자가 지정한 날짜와 시간에 정확히 알림(Alert)이 울리도록 구현하는 방법을 단계별로 살펴봅니다.

구현 개요

전체적인 동작 흐름은 다음과 같습니다.

  • 앱이 시작되면 타임 피커 다이얼로그(TimePickerDialog)가 표시됩니다.
  • 사용자가 시간을 선택하면 해당 시간으로 알람이 예약됩니다.
  • 예약된 시간이 되면 BroadcastReceiver를 통해 알림(Notification)이 발생하고 진동 및 소리가 재생됩니다.

1단계: 새 프로젝트 생성

Android Studio에서 File → New Project로 이동하여 새 프로젝트를 생성하고, 필요한 모든 세부 정보를 입력합니다.

2단계: 레이아웃 파일 작성

res/layout/activity_main.xml에 다음 코드를 추가합니다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
</LinearLayout>

3단계: MainActivity 작성

src/MainActivity.java에 다음 코드를 추가합니다. 이 클래스는 TimePickerDialog의 콜백을 받아 알람을 예약하는 핵심 역할을 담당합니다.

package app.com.sample;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.DialogFragment;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.TimePickerDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TimePicker;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Objects;
public class MainActivity extends AppCompatActivity implements TimePickerDialog.OnTimeSetListener{
    String timeText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DialogFragment timePicker = new TimePickerFragment();
        timePicker.show(getSupportFragmentManager(), "time picker");
    }
    @Override
    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, hourOfDay);
        c.set(Calendar.MINUTE, minute);
        c.set(Calendar.SECOND, 0);
        updateTimeText(c);
        startAlarm(c);
    }
    private void updateTimeText(Calendar c) {
        timeText = "Alarm set for: ";
        timeText += DateFormat.getTimeInstance(DateFormat.SHORT).format(c.getTime());
    }
    private void startAlarm(Calendar c) {
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(this, NotificationPublisher.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1, intent, 0);
        if (c.before(Calendar.getInstance())) {
            c.add(Calendar.DATE, 1);
        }
        Objects.requireNonNull(alarmManager).setExact(AlarmManager.RTC_WAKEUP,
        c.getTimeInMillis(), pendingIntent);
    }
}
핵심 포인트: setExact() 메서드를 사용하면 지정된 시간에 정확하게 알람이 울립니다. 또한 선택한 시간이 이미 지난 경우 자동으로 다음 날로 조정되도록 처리했습니다.

4단계: NotificationPublisher 클래스 생성

새 클래스 NotificationPublisher를 만들고 다음 코드를 추가합니다. 이 BroadcastReceiver는 알람이 울리는 시점에 시스템으로부터 호출되어 알림을 게시합니다.

package app.com.sample;
import android.app.Notification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import androidx.core.app.NotificationCompat;
public class NotificationPublisher extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        NotificationHelper notificationHelper = new NotificationHelper(context);
        NotificationCompat.Builder nb = notificationHelper.getChannelNotification();
        notificationHelper.getManager().notify(1, nb.build());
        Notification notification = nb.build();
        notification.defaults |= Notification.DEFAULT_VIBRATE;
        notification.defaults |= Notification.DEFAULT_SOUND;
    }
}

5단계: NotificationHelper 클래스 생성

새 클래스 NotificationHelper를 만들고 다음 코드를 추가합니다. Android 8.0(Oreo) 이상에서는 반드시 알림 채널(Notification Channel)을 생성해야 하므로, 버전에 따라 분기 처리를 해줍니다.

package app.com.sample;
import android.annotation.TargetApi;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.Build;
import androidx.core.app.NotificationCompat;
class NotificationHelper extends ContextWrapper {
    public static final String channelID = "channelID";
    public static final String channelName = "Channel Name";
    private NotificationManager notificationManager;
    public NotificationHelper(Context base) {
        super(base);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createChannel();
        }
    }
    @TargetApi(Build.VERSION_CODES.O)
    private void createChannel() {
        NotificationChannel channel = new NotificationChannel(channelID, channelName,
        NotificationManager.IMPORTANCE_HIGH);
        getManager().createNotificationChannel(channel);
    }
    public NotificationManager getManager() {
        if (notificationManager == null) {
            notificationManager = (NotificationManager)
            getSystemService(Context.NOTIFICATION_SERVICE);
        }
        return notificationManager;
    }
    public NotificationCompat.Builder getChannelNotification() {
        return new NotificationCompat.Builder(getApplicationContext(), channelID)
            .setContentTitle("Scheduled Alert")
            .setContentText("Your Alert is Ringing")
            .setSmallIcon(R.drawable.ic_alarm);
        }
    }

6단계: TimePickerFragment 클래스 생성

새 클래스 TimePickerFragment를 만들고 다음 코드를 추가합니다. 이 다이얼로그 프래그먼트는 현재 시간을 기본값으로 하는 타임 피커를 화면에 표시합니다.

package app.com.sample;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.text.format.DateFormat;
import java.util.Calendar;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
public class TimePickerFragment extends DialogFragment {
    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Calendar c = Calendar.getInstance();
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);
        return new TimePickerDialog(getActivity(), (TimePickerDialog.OnTimeSetListener) getActivity(),
        hour, minute, DateFormat.is24HourFormat(getActivity()));
    }
}

7단계: 매니페스트 설정

androidManifest.xml에 다음 코드를 추가합니다. BroadcastReceiver가 정상적으로 동작하려면 매니페스트에 receiver를 등록해야 합니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.sample">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    <receiver android:name=".NotificationPublisher"></receiver>
</application>

앱 실행하기

이제 애플리케이션을 실행해 보겠습니다. 실제 Android 모바일 기기가 컴퓨터에 연결되어 있다고 가정합니다. Android Studio에서 앱을 실행하려면 프로젝트의 액티비티 파일 중 하나를 연 뒤, 툴바에서 Run Android에서 특정 날짜와 시간에 알림이 울리도록 설정하는 방법 아이콘을 클릭합니다. 목록에서 본인의 모바일 기기를 선택하면, 기기에 아래와 같은 기본 화면이 표시됩니다.

Android에서 특정 날짜와 시간에 알림이 울리도록 설정하는 방법

화면이 나타나면 타임 피커에서 원하는 시간을 선택하세요. 지정한 시간이 되면 "Scheduled Alert" 제목의 알림이 진동과 함께 표시되는 것을 확인할 수 있습니다.