AlarmManager
は、アラームを作成するためのクラスです。アラームを使うと、将来の特定の時間に特定のコードが実行されるようにアプリをスケジュールすることができます。
public class AlarmManager extends Object{}
タイマーのようなものを使用するよりも、AlarmManager
クラスを使用してアラームを作成し、スケジューリングする方がより良く、より効率的です。
AlarmManager
は、システムアラームサービスへのアクセスを提供してくれるので、スケジューリングアルゴリズムを発明するようなことはありません。
AlarmManager は主に
BroadcastReceivers` と一緒に使用されます。その仕組みは以下の通りです。
*最初のアラームが鳴る、または鳴らない。
- システムは
intent
をブロードキャストします。これは登録されていたintent
です。 - ターゲットアプリケーションがまだ実行されていない場合は、自動的に起動します。
- デバイスがスリープしても、すでに登録されているアラームは保持されます。
- デバイスがスリープしているときにアラームが鳴った場合は、デバイスが起こされます。これはオプションです。
- ユーザーがデバイスの電源を切ったり、再起動した場合、アラームはクリアされます。
ブロードキャストの処理が終わるまで、電話がスリープしないことが保証されます。ブロードキャストの処理は、android.content.BroadcastReceiver
のonReceive()
メソッドで行います。これは、このクラスを派生させた後にオーバーライドするメソッドです。
onReceive()メソッドが実行されている間は、
AlarmManager`はCPUのウェイクロックを保持します。そのため、デバイスはスリープしません。
そして、onReceive()
の実行が終了して戻ると、AlarmManager
はウェイクロックを解除します。
しかし、onReceive()
メソッドが終了すると同時に、端末がすぐにスリープしてしまうことがあります。端末がすぐにスリープしてしまったため、Context.startService()
を使ってサービスをリクエストしていても、そのサービスは開始されません。これは、呼び出される前にデバイスがスリープしてしまったためです。しかし、最初のウェイクロックはもはや行われていません。これはonReceive()
が返ってきた瞬間に解除されたものです。では、どうすればいいのでしょうか?まず、BroadcastReceiver
とService
に別のウェイクロックを実装します。このウェイクロックにより、サービスが利用可能になるまでデバイスが動作することが保証されます。
では、AlarmManager
はいつ使用し、いつ使用しないのでしょうか?AlarmManagerはスケジューリングのために使います。タイミングやティッキングの操作には使用しないでください。また、スケジューリング操作にタイマーを使用しないでください。AlarmManager
を使ったスケジュールコードは、アプリケーションが常に実行されている必要はありません。タイマーを使った場合には、常に実行していなければなりません。これはメモリと処理時間の無駄です。
Android OSでは、アラームをシフトさせることで、ウェイクアップやバッテリー消費を最小限に抑えています。これはAndroid API 19(KitKat)からです。このアラームは厳密には正確ではないかもしれません。厳密に行う必要がある場合は、setExact()
メソッドを使用してください。
AlarmManager "は直接インスタンス化されません。代わりに、Context
クラスの静的なgetSystemService()を使用します。その際、
Context.ALARM_SERVICE` フラグを渡します。
Context.getSystemService(Context.ALARM_SERVICE
例題 1: Kotlin Android で目覚まし時計を作る
この例題は、アラームとBroadcastreceiverの使い方を学ぶためのものです。その過程で、簡単な目覚まし時計を作ります。この例では、これらの技術を実践的に学ぶことができます。
ステップ 1: Kotlin プロジェクトの作成
まず、Android Studio で空の Kotlin プロジェクトを作成します。
Step 2: 依存関係
特別な依存関係は必要ありません。ただし、コルーチンを使用しますので、必ず Kotlin を使用してください。
ステップ 3: パーミッション
このプロジェクトにはパーミッションは必要ありません。ただし、この目覚まし時計では BroadcastReceiver
を使用しているので、AndroidManifest.xml
に receiver
を登録してください。
<receiver
android:name=".AlarmReceiver"
android:exported="false" />
Step 4: レイアウトの設計
必要なレイアウトは、
を使って制約をかけるだけです。MainActivity
レイアウトの1つだけです。TextViewやボタンを追加して、以下のように
ConstraintLayout
activity_main.xmlを参照してください。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background_black"
tools:context=".MainActivity">
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginHorizontal="50dp"
android:background="@drawable/background_white_ring"
app:layout_constraintBottom_toTopOf="@id/onOffButton"
app:layout_constraintDimensionRatio="H,1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/timeTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="09:30"
android:textColor="@color/white"
android:textSize="50sp"
app:layout_constraintBottom_toTopOf="@id/ampmTextView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="@+id/ampmTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="AM"
android:textColor="@color/white"
android:textSize="25sp"
app:layout_constraintBottom_toTopOf="@id/onOffButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/timeTextView" />
<Button
android:id="@+id/onOffButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/on_alarm"
app:layout_constraintBottom_toTopOf="@id/changeAlarmTimeButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/changeAlarmTimeButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/change_time"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
ステップ 5: モデルクラスの作成
モデルクラスを作成します。Kotlinのデータクラスで、2つの整数とブール値をconstructor
で受け取ります。整数は「時」と「分」で、ブーリアンは「オンオフ」です。これらは、目覚まし時計に表示されるタイマービューを構築するために使用されます。
AlarmDisplayModel.kt
。
package com.example.alarmclock
data class AlarmDisplayModel(
val hour: Int,
val minute: Int,
var onOff: Boolean
) {
val timeText: String
get() {
val h = "%02d".format(if (hour < 12) hour else hour - 12)
val m = "%02d".format(minute)
return "$h:$m"
}
val ampmText: String
get() {
return if (hour < 12) "AM" else "PM"
}
val onOffText: String
get() {
return if (onOff) "알람 끄기" else "알람 켜기"
}
fun makeDataForDB(): String {
return "$hour:$minute"
}
}
Step 5: アラームレシーバーの作成
これは、broadcast receiver
を拡張して、onReceive()
メソッドをオーバーライドすることで行います。onReceive()`の中では、通知チャンネルを作成して、通知を作成します。
以下にそのコードを示します。
AlarmReceiver.kt
。
package com.example.alarmclock
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
class AlarmReceiver: BroadcastReceiver() {
companion object {
const val NOTIFICATION_ID = 100
const val NOTIFICATION_CHANNEL_ID = "1000"
}
override fun onReceive(context: Context, intent: Intent) {
createNotificationChannel(context)
notifyNotification(context)
}
private fun createNotificationChannel(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"기상 알람",
NotificationManager.IMPORTANCE_HIGH
)
NotificationManagerCompat.from(context).createNotificationChannel(notificationChannel)
}
}
private fun notifyNotification(context: Context) {
with(NotificationManagerCompat.from(context)) {
val build = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setContentTitle("알람")
.setContentText("일어날 시간입니다.")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setPriority(NotificationCompat.PRIORITY_HIGH)
notify(NOTIFICATION_ID, build.build())
}
}
}
Step 6: メインの Activity
の作成
最後に、以下のように
を作成します。MainActivity
を作成します。MainActivity
.kt
package com.example.alarmclock
import android.app.AlarmManager
import android.app.PendingIntent
import android.app.TimePickerDialog
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import java.util.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initOnOffButton()
initChangeAlarmTimeButton()
val model = fetchDataFromSharedPreferences()
renderView(model)
}
private fun initOnOffButton() {
val onOffButton = findViewById<Button>(R.id.onOffButton)
onOffButton.setOnClickListener {
val model = it.tag as? AlarmDisplayModel ?: return@setOnClickListener
val newModel = saveAlarmModel(model.hour, model.minute, model.onOff.not())
renderView(newModel)
if (newModel.onOff) {
// 켜진 경우 -> 알람을 등록
val calendar = Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, newModel.hour)
set(Calendar.MINUTE, newModel.minute)
if (before(Calendar.getInstance())) {
add(Calendar.DATE, 1)
}
}
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(this, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this, ALARM_REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT)
alarmManager.setInexactRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
} else {
cancelAlarm()
}
}
}
private fun initChangeAlarmTimeButton() {
val changeAlarmButton = findViewById<Button>(R.id.changeAlarmTimeButton)
changeAlarmButton.setOnClickListener {
val calendar = Calendar.getInstance()
TimePickerDialog(this, { picker, hour, minute ->
val model = saveAlarmModel(hour, minute, false)
renderView(model)
cancelAlarm()
}, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), false).show()
}
}
private fun saveAlarmModel(
hour: Int,
minute: Int,
onOff: Boolean
): AlarmDisplayModel {
val model = AlarmDisplayModel(
hour = hour,
minute = minute,
onOff = onOff
)
val sharedPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
with(sharedPreferences.edit()) {
putString(ALARM_KEY, model.makeDataForDB())
putBoolean(ONOFF_KEY, model.onOff)
commit()
}
return model
}
private fun fetchDataFromSharedPreferences():AlarmDisplayModel {
val sharedPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
val timeDBValue = sharedPreferences.getString(ALARM_KEY, "9:30") ?: "9:30"
val onOffDBValue = sharedPreferences.getBoolean(ONOFF_KEY, false)
val alarmData = timeDBValue.split(":")
val alarmModel = AlarmDisplayModel(
hour = alarmData[0].toInt(),
minute = alarmData[1].toInt(),
onOff = onOffDBValue
)
// 보정 보정 예외처리
val pendingIntent = PendingIntent.getBroadcast(this, ALARM_REQUEST_CODE, Intent(this, AlarmReceiver::class.java), PendingIntent.FLAG_NO_CREATE)
if ((pendingIntent == null) and alarmModel.onOff) {
// 알람은 꺼져있는데, 데이터는 켜저있는 경우
alarmModel.onOff = false
} else if ((pendingIntent != null) and alarmModel.onOff.not()){
// 알람은 켜져있는데, 데이터는 꺼져있는 경우
// 알람을 취소함
pendingIntent.cancel()
}
return alarmModel
}
private fun renderView(model: AlarmDisplayModel) {
findViewById<TextView>(R.id.ampmTextView).apply {
text = model.ampmText
}
findViewById<TextView>(R.id.timeTextView).apply {
text = model.timeText
}
findViewById<Button>(R.id.onOffButton).apply {
text = model.onOffText
tag = model
}
}
private fun cancelAlarm() {
val pendingIntent = PendingIntent.getBroadcast(this, ALARM_REQUEST_CODE, Intent(this, AlarmReceiver::class.java), PendingIntent.FLAG_NO_CREATE)
pendingIntent?.cancel()
}
companion object {
private const val SHARED_PREFERENCES_NAME = "time"
private const val ALARM_KEY = "alarm"
private const val ONOFF_KEY = "onOff"
private const val ALARM_REQUEST_CODE = 1000
}
}
ステップ 7: 実行
最後にプロジェクトを実行します。
Reference
コードの参考リンクを紹介します。
番号 | リンク |
---|---|
1.|コードのダウンロード |
例2: アラームの起動方法
そのような携帯電話のようなソフトウェアアプリケーションの一つが「アラーム」です。あるいは、未来に何かが起こることをスケジュールできるアプリです。これは、デスクトップアプリケーションよりもモバイル機器ではさらに重要です。
なぜなら、私たちはモバイル機器を放置したり、電源を切ったりすることはありません。モバイル機器は、私たちのパーソナルアシスタントです。そのため、デスクトップアプリケーションよりもパーソナルな使い方をします。
そこでAndroidでは、AlarmManager
というリッチなクラスを提供しています。これは、システムサービスにアクセスするためのクラスです。このクラスは明らかにパブリックで、java.lang.Object
から派生しています。
これがその定義です。
public class AlarmManager extends Object{}
何を作るの?
それでは、簡単なアンドロイドの AlarmManager
の例を見てみましょう。アンドロイドでアラームを開始したり、キャンセルしたりする方法を見てみましょう。基本的なエディットテキストがあります。ユーザーはアラームが鳴るまでの時間をミリ秒単位で入力します。アラームが鳴ると、シンプルな Toast
メッセージが表示されます。
プロジェクトの構成
プロジェクトの構成は以下の通りです。
Step 1 - Android プロジェクトの作成
- アンドロイドスタジオで、File -- New -- New Project を選択します。
- プロジェクト名を入力します。
- 最小限のSDKを選択します。
- テンプレートから空のアクティビティまたはブラを選択します。
Step 2. - 2. build.gradle
を修正しましょう。
これが2つ目のステップです。android studioで作成したAndroidプロジェクトには、2つのbuil.gradle
ファイルがあります。ここでは、アプリレベルの build.gradle
を対象とします。
dependenciesセクションに以下のコードを追加します。
implementation 'com.android.support:appcompat-v7:24.2.1'
implementation 'com.android.support:design:24.2.1'
サポートライブラリから2つの依存関係を追加しています。AppCompat "と "design "です。
ステップ3. リソースを準備しましょう。
ここでは、レイアウトだけを用意します。私はテンプレートとしてベーシックなアクティビティを選びました。そこで、2つのレイアウトを用意しました。
- activity_main.xm : テンプレートレイアウト
- content_main.xml : これを修正します。
必要なのは、1つのエディットテキストと1つのボタンを追加することだけです。エディットテキストには、ユーザーが時間を秒単位で入力し、スタートボタンでアラームを開始します。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_paddingBottom="@dimen/activity_vertical_margin"
android_paddingLeft="@dimen/activity_horizontal_margin"
android_paddingRight="@dimen/activity_horizontal_margin"
android_paddingTop="@dimen/activity_vertical_margin"
app_layout_behavior="@string/appbar_scrolling_view_behavior"
tools_context="com.tutorials.hp.alarmmanagerstarter.MainActivity"
tools_showIn="@layout/activity_main">
<EditText
android_id="@+id/timeTxt"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignParentLeft="true"
android_layout_alignParentTop="true"
android_layout_marginTop="28dp"
android_ems="10"
android_hint="Number of seconds"
android_inputType="numberDecimal" />
<Button
android_id="@+id/startBtn"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignRight="@+id/timeTxt"
android_layout_below="@+id/timeTxt"
android_layout_marginRight="60dp"
android_layout_marginTop="120dp"
android_text="Start" />
</RelativeLayout>
ステップ4. それでは、BroadcastReceiver
クラスを作成しましょう。
BroadcastReceiverは、アンドロイドのコンポーネントのひとつです。BroadcastReceiver
はアンドロイドコンポーネントの一つで、他には Activity
, Service
, ContentProvider
があります。
BroadcastReceiver`はシステムのイベントを受信します。
これは実際には抽象クラスで、明らかに公開されています。これは java.lang.Object
から派生したものです。
public abstract class BroadcastReceiver extends Object{}
sendBroadcast()`によって送信されたインテントは、この基本クラスによって受信されます。
このクラスは抽象クラスなので、onReceive()
メソッドをオーバーライドします。
まず、javaクラスを作成します。
public class MyReceiver{}
次のようなインポートを追加します。
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
このクラスは android.content.BroadcastReceiver
から派生しています。
public class MyReceiver extends BroadcastReceiver {}
これで強制的に onReceive()
メソッドをオーバーライドすることになります。
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm Ringing...", Toast.LENGTH_SHORT).show();
}
Step 5. それでは、MainActivity
クラスの説明をします。
アクティビティは、ユーザーインターフェースを表すアンドロイドのコンポーネントです。アクティビティから派生してアクティビティを作成します。より多くのデバイスをサポートするために、AppCompatActivity
を使用します。
それでは、アクティビティを作ってみましょう。
public class MainActivity extends AppCompatActivity {}
アクティビティの上に以下のインポートを追加します。
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
アクティビティには3つのメソッドと2つのフィールドがあります。
まず、2つのフィールドを定義します。基本的には、ボタンとエディットテキストです。それらを MainActivity
クラスの中に追加します。
Button startBtn;
EditText timeTxt;
次に、メソッド go()
を作成します。このメソッドは、AlarmManager
の初期化とアラームの開始を担当します。
private void go()
{
//GET TIME IN SECONDS AND INITIALIZE INTENT
int time=Integer.parseInt(timeTxt.getText().toString());
Intent i=new Intent(this,MyReceiver.class);
//PASS CONTEXT,YOUR PRIVATE REQUEST CODE,INTENT OBJECT AND FLAG
PendingIntent pi=PendingIntent.getBroadcast(this,0,i,0);
//INITIALIZE ALARM MANAGER
AlarmManager alarmManager= (AlarmManager) getSystemService(ALARM_SERVICE);
//SET THE ALARM
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+(time*1000),pi);
Toast.makeText(MainActivity.this, "Alarm set in "+time+" seconds", Toast.LENGTH_SHORT).show();
}
次に、ボタンとedittextを初期化し、ボタンのonclickリスナーを処理するメソッドを作成します。
private void initializeViews()
{
timeTxt= (EditText) findViewById(R.id.timeTxt);
startBtn= (Button) findViewById(R.id.startBtn);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
go();
}
});
}
Step 6. AndroidManifest`をチェックしよう
androidmanifest.xmlを確認します。マニフェストに
BroadcastReceiver` クラスが登録されていることを確認しましょう。
broadcastreceiver`クラスが登録されていることがわかります。
<receiver android_name="MyReceiver" >
</receiver>
私の場合は次のようになっています。
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="com.tutorials.hp.alarmmanagerstarter">
<application
android_allowBackup="true"
android_icon="@mipmap/ic_launcher"
android_label="@string/app_name"
android_supportsRtl="true"
android_theme="@style/AppTheme">
<activity
android_name=".MainActivity"
android_label="@string/app_name"
android_theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android_name="android.intent.action.MAIN" />
<category android_name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android_name="MyReceiver" >
</receiver>
</application>
</manifest>
Example: Android AlarmManager
- Toast
の表示をスケジュールする
Androidエンジニアは、APIレベル1でAlarmManager
クラスを追加しましたので、アンドロイドの初期から存在しています。このクラスを使うと、将来行われるであろう操作をスケジューリングすることができます。AlarmManager`では、将来実行されるコードを設定することができます。
このコードが実行されるためにアプリが起動している必要がないというのは素晴らしいことです。もちろん、アプリは起動されますが、登録された時間にのみ実行されます。Alarm Maanagerは、android.appパッケージに属し、java.lang.Object.Alarmを継承しています。
端末がスリープ状態であっても、登録されている限りアラームは保持されます。AlarmManagerについての詳細はこちらをご覧ください。
スクリーンショット
- 以下はプロジェクトのスクリーンショットです。

この例でよくある質問を説明します。
- アンドロイドの
AlarmManager
の使い方。
AlarmManager
とは何ですか?
- アンドロイドの
AlarmManager
とは?
Toast
を使った簡単な AlarmManager
の例です。
使用したツール
このサンプルは、以下のツールを使って作成しました。
- Windows 8
- アンドロイドスタジオ IDE
- Genymotion エミュレータ
ソースコード
それでは早速、ソースコードを見てみましょう。
Build.Gradle
- 通常、アンドロイドプロジェクトでは、2つの
build.gradle
ファイルがあります。1つはアプリレベルの build.gradle
で、もう1つはプロジェクトレベルの build.gradle
です。appレベルはappフォルダ内にあり、通常はここに依存関係を追加し、コンパイルとターゲットのsdkを指定します。
- また、
AppCompat
やデザインサポートライブラリの依存関係も追加します。
- MainActivity "は "AppCompatActivity "から派生したもので、デザインサポートライブラリの "FloatingActionButton "も使用しています。
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "25.0.1"
defaultConfig {
applicationId "com.tutorials.hp.alarmmanagerstarter"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
implementation 'com.android.support:appcompat-v7:24.2.1'
implementation 'com.android.support:design:24.2.1'
}
MyReceiver.java"
- 私たちの
Broadcast Receiver
クラスです。
- このクラスは、android.app.content.BroadCastReceiverを継承しています。
- そして、
OnReceive()
メソッドをオーバーライドします。ここには、アラームが鳴ったときに実行されるコードを書きます。
- ここでは、単純に
Toast
メッセージを表示します。
package com.tutorials.hp.alarmmanagerstarter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
/*
RING ALARM WHEN IN WHEN WE RECEIVE OUR BROADCAST
*/
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm Ringing...", Toast.LENGTH_SHORT).show();
}
}
MainActivity
.java
- ランチャーアクティビティです。
ActivityMain.xml
をこのアクティビティのコンテンツビューとしてインフレーションします。
- このアクティビティ内のビューとウィジェットを初期化します。
- また、
AlarmManager
オブジェクトを使用して、このアクティビティ内でアラームの初期化と開始を行います。
package com.tutorials.hp.alarmmanagerstarter;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
Button startBtn;
EditText timeTxt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initializeViews();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
/*
INITIALIZE VIEWS
*/
private void initializeViews()
{
timeTxt= (EditText) findViewById(R.id.timeTxt);
startBtn= (Button) findViewById(R.id.startBtn);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
go();
}
});
}
/*
INITIALIZE AND START OUR ALARM
*/
private void go()
{
//GET TIME IN SECONDS AND INITIALIZE INTENT
int time=Integer.parseInt(timeTxt.getText().toString());
Intent i=new Intent(this,MyReceiver.class);
//PASS CONTEXT,YOUR PRIVATE REQUEST CODE,INTENT OBJECT AND FLAG
PendingIntent pi=PendingIntent.getBroadcast(this,0,i,0);
//INITIALIZE ALARM MANAGER
AlarmManager alarmManager= (AlarmManager) getSystemService(ALARM_SERVICE);
//SET THE ALARM
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+(time*1000),pi);
Toast.makeText(MainActivity.this, "Alarm set in "+time+" seconds", Toast.LENGTH_SHORT).show();
}
}
アクティビティメイン.xml
- テンプレートレイアウトです。
- ContentMain.xmlを含みます。
- また、appbarlayout、ツールバー、floatingaction butttonも定義しています。
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_fitsSystemWindows="true"
tools_context="com.tutorials.hp.alarmmanagerstarter.MainActivity">
<android.support.design.widget.AppBarLayout
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android_id="@+id/toolbar"
android_layout_width="match_parent"
android_layout_height="?attr/actionBarSize"
android_background="?attr/colorPrimary"
app_popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
android_id="@+id/fab"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_gravity="bottom|end"
android_layout_margin="@dimen/fab_margin"
android_src="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
ContentMain.xml
- コンテンツのレイアウトです。
MainActivity
の内部に表示されるビューやウィジェットを定義します。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_paddingBottom="@dimen/activity_vertical_margin"
android_paddingLeft="@dimen/activity_horizontal_margin"
android_paddingRight="@dimen/activity_horizontal_margin"
android_paddingTop="@dimen/activity_vertical_margin"
app_layout_behavior="@string/appbar_scrolling_view_behavior"
tools_context="com.tutorials.hp.alarmmanagerstarter.MainActivity"
tools_showIn="@layout/activity_main">
<EditText
android_id="@+id/timeTxt"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignParentLeft="true"
android_layout_alignParentTop="true"
android_layout_marginTop="28dp"
android_ems="10"
android_hint="Number of seconds"
android_inputType="numberDecimal" />
<Button
android_id="@+id/startBtn"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignRight="@+id/timeTxt"
android_layout_below="@+id/timeTxt"
android_layout_marginRight="60dp"
android_layout_marginTop="120dp"
android_text="Start" />
</RelativeLayout>
実行するには
- 上記プロジェクトをダウンロードします。
- ZIPファイルが出てきますので、それを解凍します。
- Android Studioを開きます。
- すでに開いているプロジェクトを閉じます。
- メニューバーの「ファイル」→「新規作成」→「プロジェクトのインポート」をクリックします。
- プロジェクトをインポートする先のフォルダを選択します。
- Androidプロジェクトを選択します。
- OK "をクリックします。
- これで、プロジェクトのインポートが完了しました。
おわりに
今回は、簡単なアンドロイドの AlarmManager
の例を見ました。
Example: アンドロイドの繰り返し/反復アラームのスケジュール
AlarmManager "はAndroidの初期から存在しています。これにより、将来のタスクをスケジュールすることができます。
AlarmManager`を使うと、将来実行されるコードを設定することができます。
AlarmManagerは、android.app
パッケージに属し、java.lang.Object
を継承しています。デバイスがスリープ状態であっても、アラームは登録されている限り保持されます。今回の例では,周期的に繰り返されるアラームを扱う方法を見てみましょう。
与えられた秒数の後にToast
メッセージの表示をスケジュールします。例えば、ユーザが edittexts
に 5 を入力して start ボタンをクリックすると、5 秒ごとに Toast
メッセージが表示され、ユーザが cancel ボタンをクリックしてアラームをキャンセルするまで、表示されます。このようにして、アラームの繰り返しを開始し、それをキャンセルする方法を見ることができます。AlarmManagerの詳細はこちらを参照してください。
この例でよくある質問
- アンドロイドの
AlarmManager
の使い方。
- アンドロイドで繰り返し/反復するアラームを設定し、それらをキャンセルする方法。
- アンドロイドでアラームを開始したり、キャンセルしたりする方法。
- アンドロイドで将来行われる作業をスケジュールするには?
- 簡単な繰り返しの
AlarmManager
の例として、Toast
があります。
使用したツール
このサンプルは、以下のツールを使って作成しました。
-
Windows 8
-
AndroidStudio IDE
-
Genymotion エミュレータ
-
言語 : Java
-
Topic : Android Recurring Alarms,
AlarmManager
, Start Cancel Repeating alarms
-
使用したライブラリ
-
サードパーティ製のライブラリは一切使用していません。
ソースコード
ソースコードを見てみましょう。
Build.Gradle
通常、アンドロイドプロジェクトでは、2つの build.gradle
ファイルがあります。1つはアプリレベルの build.gradle
で、もう1つはプロジェクトレベルの build.gradle
です。appレベルはappフォルダ内にあり、通常はここに依存関係を追加したり、コンパイルおよびターゲットSDKを指定したりします。
また、AppCompat
やデザインサポートライブラリの依存関係も追加します。
MainActivity "は "AppCompatActivity "から派生したもので、デザインサポートライブラリの "FloatingActionButton "も使用します。
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "com.tutorials.hp.repeatingalarm"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidtestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'com.android.support:appcompat-v7:26.+'
implementation 'com.android.support.constraint:constraint-layout:1.0.0-alpha7'
implementation 'com.android.support:design:26.+'
testImplementation 'junit:junit:4.12'
}
MyReceiver.java
- 私たちの
MyReceiver
クラスです。
android.content.BroadcastReceiver
から派生しています。
- onReceive()メソッドをオーバーライドし、アラームが鳴ったときに行う処理をここで行います。
package com.tutorials.hp.repeatingalarm;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
/*
RING ALARM WHEN IN WHEN WE RECEIVE OUR BROADCAST
*/
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm Ringing...", Toast.LENGTH_SHORT).show();
}
}
MainActivity
.java
- 私たちの
MainActivity
クラスです。
- サポートライブラリのアクションバー機能を使用するアクティビティのベースクラスである
AppCompatActivity
から派生しています。
- メソッド:
onCreate()
, initializeViews()
, initializeAlarmManager()
, go()
.
setContentView()
メソッドを使用して、activity_main.xml
からインフレーションを行います。
- 使用しているビューは、
EditTexts
とbuttons
です。
findViewById()
を使用して、レイアウト仕様からこれらを参照します。
AlarmManager
を初期化します。
- setInExactRepeating()`でアラームを開始します。
package com.tutorials.hp.repeatingalarm;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
Button startBtn,cancelBtn;
EditText timeTxt;
AlarmManager alarmManager;
PendingIntent pi;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initializeViews();
initializeAlarmManager();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
go();
}
});
}
/*
INITIALIZE VIEWS
*/
private void initializeViews()
{
timeTxt= (EditText) findViewById(R.id.timeTxt);
startBtn= (Button) findViewById(R.id.startBtn);
cancelBtn= (Button) findViewById(R.id.cancelBtn);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
go();
}
});
cancelBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(alarmManager != null)
{
alarmManager.cancel(pi);
}
}
});
}
/*
INITIALIZE AND START OUR ALARM
*/
private void initializeAlarmManager()
{
// INITIALIZE INTENT
Intent intent=new Intent(this,MyReceiver.class);
//PASS CONTEXT,YOUR PRIVATE REQUEST CODE,INTENT OBJECT AND FLAG
pi= PendingIntent.getBroadcast(this,0,intent,0);
//INITIALIZE ALARM MANAGER
alarmManager= (AlarmManager) this.getSystemService(ALARM_SERVICE);
}
/*
START OUR ALARM
*/
private void go()
{
//GET TIME IN SECONDS
int time=Integer.parseInt(timeTxt.getText().toString());
//SET THE ALARM
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+(time*1000),time*1000,pi);
Toast.makeText(MainActivity.this, "Alarm set in "+time+" seconds", Toast.LENGTH_SHORT).show();
}else
{
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME,System.currentTimeMillis()+(time*1000),time*1000,pi);
Toast.makeText(MainActivity.this, "Yes Alarm set in "+time+" seconds", Toast.LENGTH_SHORT).show();
}
}
}
ActivityMain.xml
を参照してください。
これは、MainActivity
のテンプレート・レイアウトです。ルートとなるレイアウトタグはCoordinatorLayout
です。CoordinatorLayout`は、framelayoutをさらにパワーアップさせたビューグループです。
CoordinatorLayout
は主に2つのユースケースを想定しています。トップレベルのアプリケーションの装飾またはクロームレイアウトとして 1つまたは複数の子ビューとの特定のインタラクションのためのコンテナとして。
CoordinatorLayout
の中には、AppBarLayout
、FloatingActionButton を追加し、content_main.xml
をインクルードしています。
AppBarLayout
は、マテリアルデザインコンセプトのスクロール機能を実装した、縦型の LinearLayout です。
CoordinatorLayout
の直接の子でなければならず、そうでなければ多くの機能が動作しません。
AppBarLayout
の中に、青い色をした toolbar
を追加します。
- これはテンプレートレイアウトなので、ここではなく、
content_main.xml
にウィジェットを追加します。
- これは、
android.support.design.widget.VisibilityAwareImageButton
から派生したクラスです。これは、ユーザーインターフェイスで見られる丸いボタンです。
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
tools_context="com.tutorials.hp.repeatingalarm.MainActivity">
<android.support.design.widget.AppBarLayout
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android_id="@+id/toolbar"
android_layout_width="match_parent"
android_layout_height="?attr/actionBarSize"
android_background="?attr/colorPrimary"
app_popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
android_id="@+id/fab"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_gravity="bottom|end"
android_layout_margin="@dimen/fab_margin"
app_srcCompat="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
ContentMain.xml
ContentMain.xml
ファイルを作成します。
MainActivity
にインフレーションされるものとします。
- ルートタグは
ConstraintLayout
です。
EditTexts
と2つのボタンが含まれています。
- ユーザーは、アラームが鳴ってからの秒数をエディットテキストに入力します。
- アラームを開始するには、スタートボタンをクリックします。
- アラームをキャンセルするにはCancelボタンをクリックします。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
app_layout_behavior="@string/appbar_scrolling_view_behavior"
tools_context="com.tutorials.hp.repeatingalarm.MainActivity"
tools_showIn="@layout/activity_main">
<LinearLayout
android_layout_width="368dp"
android_layout_height="327dp"
android_orientation="vertical"
app_layout_constraintTop_toTopOf="parent"
android_layout_marginTop="8dp">
<EditText
android_id="@+id/timeTxt"
android_layout_width="wrap_content"
android_layout_height="wrap_content"
android_layout_alignParentLeft="true"
android_layout_alignParentTop="true"
android_ems="10"
android_hint="Number of seconds"
android_inputType="numberDecimal"
/>
<Button
android_id="@+id/startBtn"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_alignRight="@+id/timeTxt"
android_layout_below="@+id/timeTxt"
android_text="Start"
/>
<Button
android_id="@+id/cancelBtn"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_layout_alignRight="@+id/timeTxt"
android_layout_below="@+id/timeTxt"
android_text="Cancel"
/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
Video/Preview
- YouTubeチャンネルには、約1000のチュートリアルがあり、以下のものはその一つです。
https://www.youtube.com/watch?v=23Gw-11JFqc
ダウンロード
- 以下からプロジェクトの全容をダウンロードできます。ソースコードはしっかりとコメントされています。