【Android】AlarmManagerで毎日指定した時刻に通知を表示する方法
Androidで毎日特定の時刻に通知を表示する方法
この記事では、AndroidアプリにおいてAlarmManagerとBroadcastReceiverを組み合わせて、ユーザーが選択した日時に通知を表示する仕組みを実装する方法を解説します。リマインダーやお知らせ機能など、定期的な通知が必要なアプリを作る際の基本となるパターンなので、ぜひ参考にしてください。
実装の流れは次のとおりです。
- DatePickerDialogでユーザーに日付を選択させる
- 選択された日時をもとにAlarmManagerへアラームを登録する
- 指定時刻にBroadcastReceiverが起動し、NotificationManagerで通知を発行する
ステップ1:新規プロジェクトを作成する
Android Studioを起動し、メニューからFile → New Projectを選択します。必要な情報を入力して新しいプロジェクトを作成しましょう。テンプレートは「Empty Activity」で問題ありません。
ステップ2:レイアウトファイル(activity_main.xml)
res/layout/activity_main.xml に以下のコードを記述します。タップすると日付選択ダイアログが開くTextViewを1つ配置しています。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:padding="16dp"
tools:context=".MainActivity">
<TextView
android:id="@+id/btnDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Select Date"
android:onClick="setDate"
android:padding="16dp"/>
</RelativeLayout>
ステップ3:MainActivity.java
src/MainActivity.java に以下のコードを追加します。日付が選択されると updateLabel() 内で通知オブジェクトを生成し、scheduleNotification() を通じてAlarmManagerにアラームを登録します。
package app.tutorialspoint.com.notifyme;
import android.app.AlarmManager;
import android.app.DatePickerDialog;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default";
Button btnDate;
final Calendar myCalendar = Calendar.getInstance();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnDate = findViewById(R.id.btnDate);
}
private void scheduleNotification(Notification notification, long delay) {
Intent notificationIntent = new Intent(this, MyNotificationPublisher.class);
notificationIntent.putExtra(MyNotificationPublisher.NOTIFICATION_ID, 1);
notificationIntent.putExtra(MyNotificationPublisher.NOTIFICATION, notification);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
assert alarmManager != null;
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, delay, pendingIntent);
}
private Notification getNotification(String content) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this,
default_notification_channel_id);
builder.setContentTitle("Scheduled Notification");
builder.setContentText(content);
builder.setSmallIcon(R.drawable.ic_launcher_foreground);
builder.setAutoCancel(true);
builder.setChannelId(NOTIFICATION_CHANNEL_ID);
return builder.build();
}
DatePickerDialog.OnDateSetListener date = new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
myCalendar.set(Calendar.YEAR, year);
myCalendar.set(Calendar.MONTH, monthOfYear);
myCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
updateLabel();
}
};
public void setDate(View view) {
new DatePickerDialog(MainActivity.this, date,
myCalendar.get(Calendar.YEAR),
myCalendar.get(Calendar.MONTH),
myCalendar.get(Calendar.DAY_OF_MONTH)).show();
}
private void updateLabel() {
String myFormat = "dd/MM/yy"; // 表示形式はここで変更できます
SimpleDateFormat sdf = new SimpleDateFormat(myFormat, Locale.getDefault());
Date date = myCalendar.getTime();
btnDate.setText(sdf.format(date));
scheduleNotification(getNotification(btnDate.getText().toString()), date.getTime());
}
}
ステップ4:MyNotificationPublisher.java
続いて、アラームを受け取って実際に通知を表示するためのBroadcastReceiverクラスを作成します。src/MyNotificationPublisher.java に以下のコードを追加してください。Android 8.0(API 26)以降では通知チャンネルの作成が必須となるため、その処理も含まれています。
package app.tutorialspoint.com.notifyme;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import static app.tutorialspoint.com.notifyme.MainActivity.NOTIFICATION_CHANNEL_ID;
public class MyNotificationPublisher extends BroadcastReceiver {
public static String NOTIFICATION_ID = "notification-id";
public static String NOTIFICATION = "notification";
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = intent.getParcelableExtra(NOTIFICATION);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", importance);
assert notificationManager != null;
notificationManager.createNotificationChannel(notificationChannel);
}
int id = intent.getIntExtra(NOTIFICATION_ID, 0);
assert notificationManager != null;
notificationManager.notify(id, notification);
}
}
ステップ5:AndroidManifest.xml
最後に、AndroidManifest.xml にVIBRATE権限とレシーバーの宣言を追加します。receiverの登録を忘れるとアラームが受け取れず通知が表示されないので、必ず記述してください。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.tutorialspoint.com.notifyme">
<uses-permission android:name="android.permission.VIBRATE"/>
<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=".MyNotificationPublisher"/>
</application>
</manifest>
アプリを実行してみよう
それではアプリを実行してみましょう。実機のAndroidスマートフォンをPCに接続している前提で進めます。Android Studioでプロジェクト内のアクティビティファイルを開き、ツールバーのRunアイコンをクリックしてください。デバイス選択画面で自分のスマートフォンを選択すると、端末上でアプリが起動します。
アプリが起動したら、画面上の日付欄をタップしてDatePickerDialogから任意の日付を選択します。選択した日時になると、ステータスバーに「Scheduled Notification」というタイトルの通知が届くはずです。
補足ポイント
- 毎日同じ時刻に繰り返し通知したい場合:set() の代わりに setRepeating() や setInexactRepeating() を使うことで、定期実行されるアラームを簡単に実現できます。
- 絶対日時で通知したい場合:カレンダーの日時をそのまま指定するなら、ELAPSED_REALTIME_WAKEUP よりも RTC_WAKEUP を使う方が一般的です。
- Android 8.0以降:通知チャンネル未作成のまま通知を発行しても表示されないため、チャンネル作成処理は必須です。
まとめ
今回は、DatePickerDialogで取得した日時をもとにAlarmManagerでアラームを登録し、指定時刻にBroadcastReceiver経由で通知を表示する一連の流れを紹介しました。AlarmManagerとBroadcastReceiverの組み合わせは、リマインダーアプリや定期通知機能の土台となる重要な実装パターンです。ぜひ自分のアプリに応用してみてください。
-
FacebookでAndroidアプリを作成する方法|開発者サイトでの設定手順を徹底解説
この記事では、FacebookでAndroidアプリを作成する方法について詳しく解説します。AndroidアプリとFacebookを連携させるには、Facebook開発者サイトでFacebookアプリを作成し、Facebook App IDを取得する必要があります。以下の手順に従って、順番に進めていきましょう。 準備:Facebook開発者サイトで新しいアプリを追加する まず、https://developers.facebook.com/ にアクセスし、「新しいアプリを追加」をクリックしてアプリの作成を開始します。 ステップ1:アプリ名とメールアドレスを入力する 指定されたフィールドに、作
-
Android 8で通知をスヌーズする方法
多くの人にとって、一日の最後のタスクは翌日のためにアラームをセットすることでしょう。しかし実際には、スヌーズボタンを何度も押した末に、ようやく温かい布団から這い出すというのが現実ではないでしょうか。意外にも、スヌーズとスヌーズの間のわずかな時間こそ、一番深い眠りが得られる瞬間だったりします。つまり、スヌーズ機能は私たちの生活に欠かせない大切な機能なのです。そこで本記事では、Android 8の新機能「通知のスヌーズ(Snooze Notifications)」について詳しく解説します。この機能を使えば、必要なときにスマートフォンの通知を一時的に非表示にできるようになります。通知をスヌーズするメ