Androidで特定の日時にアラームを発火させる方法を徹底解説
この記事では、Androidアプリで指定した日時にアラーム(通知)を発火させる実装方法を、サンプルコードとともに段階的に解説します。AlarmManagerとTimePickerDialogを組み合わせることで、ユーザーが設定した時刻に正確に通知を表示できるようになります。
実装の全体像
本サンプルでは、アプリ起動時に時刻選択ダイアログを表示し、ユーザーが選択した時刻にAlarmManager経由で通知を発火させる仕組みを構築します。主な構成要素は以下の通りです。
- TimePickerFragment:時刻を選択するダイアログ
- AlarmManager:指定時刻にアラームをスケジュールするシステムサービス
- NotificationPublisher:アラーム発火時に通知を表示するBroadcastReceiver
- NotificationHelper:通知チャンネルの作成と通知の構築を補助するクラス
ステップ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>このサンプルでは、時刻選択ダイアログを自動的に表示するため、レイアウトはシンプルな縦方向のLinearLayoutのみで構成されています。
ステップ3:MainActivity.javaの実装
src/MainActivity.java に以下のコードを追加します。
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);
}
}このクラスでは、TimePickerDialogで選択された時刻をCalendarにセットし、startAlarm()メソッド内でAlarmManagerのsetExact()を使ってアラームを登録しています。指定時刻がすでに過ぎている場合は、翌日の同時刻に自動的に設定されるようになっている点がポイントです。
ステップ4:NotificationPublisherクラスの作成
新しいクラス「NotificationPublisher」を作成し、以下のコードを追加します。
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;
}
}BroadcastReceiverを継承したこのクラスは、AlarmManagerによって指定時刻に起動され、通知を表示します。バイブレーションとサウンドも有効化しています。
ステップ5:NotificationHelperクラスの作成
新しいクラス「NotificationHelper」を作成し、以下のコードを追加します。
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);
}
}Android 8.0(APIレベル26)以降では通知チャンネルの作成が必須のため、OSバージョンを判定してチャンネルを生成しています。通知のタイトルやテキストはここで自由にカスタマイズできます。
ステップ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()));
}
}このダイアログは、端末の現在時刻を初期値として表示し、端末の設定に応じて24時間表示/12時間表示を自動的に切り替えます。
ステップ7:AndroidManifest.xmlの設定
androidManifest.xml に以下のコードを追加します。
<?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>重要なのは、アラーム発火時に通知を表示するNotificationPublisherを<receiver>タグでマニフェストに登録することです。これを忘れるとアラームが発火しても通知が表示されません。
アプリの実行と動作確認
それでは、アプリを実行してみましょう。実機のAndroidスマートフォンをパソコンに接続していることを前提とします。Android Studioからアプリを起動するには、プロジェクトのアクティビティファイルを開き、ツールバーの実行(Run)アイコンをクリックします。接続したモバイルデバイスを選択すると、実機の画面にアプリが表示されます。
アプリを起動すると時刻選択ダイアログが表示されるので、任意の時刻を設定してください。設定した時刻になると、ステータスバーに「Scheduled Alert(予定されたアラート)」という通知が表示され、アラームが正常に動作していることを確認できます。
まとめ
本記事では、TimePickerDialogで時刻を取得し、AlarmManagerのsetExact()でアラームを登録、BroadcastReceiverで通知を表示するという一連の流れを実装しました。リマインダーアプリや通知スケジューラなど、さまざまなアプリに応用できる基本的な仕組みなので、ぜひ実際にコードを動かして挙動を確認してみてください。
-
Android TVでADBを設定して使う方法|PCとの接続手順と活用テクニック
AndroidスマートフォンであれAndroid TVであれ、OSの本質は同じです。つまり、Android TVは他のAndroidデバイスと同じように自由にカスタマイズできるということです。 Androidアプリのサイドローディングなど、本格的なカスタマイズを行いたい場合は、「Android Debug Bridge(ADB)」の力が必要になります。この記事では、ADBを使ってAndroid TVをPCに接続する方法を詳しく解説します。 PCにADBをセットアップする方法 まず最初のステップは、お使いのPCにADBをインストールすることです。そのためには、Android Developers
-
Androidで通知を保存してリマインダーを設定する方法|おすすめアプリ2選を徹底比較
Androidスマホにインストールするアプリが増えると、届く通知も自然と増えていきます。その大半は読まずにスワイプして消してしまうものですが、中には絶対に見逃せない重要な通知もあります。アプリごとに通知をブロックできる標準機能があるのはありがたいのですが、厄介なのは通知がこちらのタイミングを考慮してくれないこと。相手の都合で届き、自分が確認したいときには出てきてくれないのです。 こんな場面を想像してみてください。仕事で忙しい最中、「ピロンッ」と友達からメッセージの通知が届きます。「明日みんなで集まらない?」という内容です。返信したい気持ちはあるものの、今は作業に集中しているところ。でも、このま