본문 바로가기
JLPT

[Android] AlarmManagerをBroadcastRecieverと使う

by 엘리후 2021. 7. 5.

ある時間にアプリから通知して欲しいという場合がよくあります。目覚まし時計とかスケジュール系のアプリなど、これらの通知には時間を管理する AlarmManager 及びその関連APIを使います。

 

 

Android Studio 3.5.3
API 29

 

AlarmManager

 

いきなりですが、アプリのオプションでアラームを鳴らしたいだけなら、Intentを使ったアラーム クロックを使うと簡単です。

 

また、setExactAndAllowWhileIdleをサービスを使って繰り返す方法もあります。

短時間の単純なタイマーや時間計測にはAlarmManagerではなく、Handlerを使うことが推奨されています。

For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.

Ref: AlarmManager

https://developer.android.com/reference/android/app/AlarmManager.html

 

また、AlarmをBroadcastReceiver で受けるケースでは、ブロードキャストの制限事項 があります。

Android 8.0 を対象にしているアプリは、暗黙的なブロードキャストに対するブロードキャスト レシーバーをマニフェストで登録できなくなりました。 

明示的な登録であれば大丈夫のようです。元々の理由が暗黙的BroadcastRecieverがたくさんあると関係ないアプリも毎回呼び出しを食らってリソース、消費電力の観点からよくないと言う理由からです。

また、AlarmManagerを使う上で、Dozeモードという低消費電力モードを考えないといけないのですが、API levelによって挙動が異なります。

つまり目覚まし時計を作ろうとした場合、このあたりをうまくやらないと時間通りにアラームが鳴りません。



[Android] Doze mode で AlarmManager の繰り返しアラームを実装するには
AlarmManagerで繰り返しのアラーム機能を実装したいのですが、バックグラウンド実行制限があります。本来の機能として定期的なバックグラ...


2020-02-05 18:48

この他にタスクスケジュールを実行できるののとしてJobSchedulerやJobDispatcherなどがあります。

 

目次

1. AlarmManager

2. PendingIntent

3. BroadcastReceiver

4. サンプルコード

5. サンプル動画

 

AlarmManager


 

このクラスを直接インスタンス化してはいけないようで

Context.getSystemService(Context.ALARM_SERVICE) を使います


1 AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

 

その後、例えば繰り返しのアラームメソッド set はこのように設定します


1
2
3
4
5
alarmManager.set(
AlarmManager.RTC_WAKEUP,
5*1000, // 1sec = 1000
sender
);

 

sender は PnedingIntent のインスタンスです。

これは単発アラームの例ですが、他にもメソッドがいくつもあります。

また、API levelによって様々追加されました。AlarmManager | Android Developers

API level 19: アラーム時間の精度が低いものが使えるようになる

API level 23: Dozeモードの導入でDoze中でも起動できるメソッドの追加

API level 24: Direct callbackが使えるメソッド

set: ワンショットのアラーム, API level 19 以降では低精度


1
2
3
4
//API level 1
set(int type,
long triggerAtMillis,
PendingIntent operation)

 

set: 上記set に Direct callback が追加


1
2
3
4
5
//API level 24
set(int type, long triggerAtMillis,
String tag,
AlarmManager.OnAlarmListener listener,
Handler targetHandler)

 

setRepeating: 繰り返しアラーム


1
2
3
4
5
//API level 1
setRepeating(int type,
long triggerAtMillis,
long intervalMillis,
PendingIntent operation)

 

setInexactRepeating: 繰り返しアラーム、API level 19 以降では低精度


1
2
3
4
5
//API level 3
setInexactRepeating (int type,
long triggerAtMillis,
long intervalMillis,
PendingIntent operation)

   

setExact: setよりも正確なワンショットアラーム


1
2
3
4
//API level 19
setExact(int type,
long triggerAtMillis,
PendingIntent operation)

 

setExact: 上記setExactに Direct Callback が追加


1
2
3
4
5
6
//API level 24
setExact (int type,
long triggerAtMillis,
String tag,
AlarmManager.OnAlarmListener listener,
Handler targetHandler)

 

setAndAllowWhileIdle: setと同じだが low-power idleモードでも実行される。


1
2
3
4
//API level 23
setAndAllowWhileIdle (int type,
long triggerAtMillis,
PendingIntent operation)

 

 

setExactAndAllowWhileIdle: setExactと同じだが low-power idleモードでも実行される。


1
2
3
4
//API level 23
setExactAndAllowWhileIdle (int type,
long triggerAtMillis,
PendingIntent operation)

Doze中でも定期的にアラームを出にはこれらを使います。

 

 

setWindow: 設定したwindow内でアラームが実行


1
2
3
4
5
//API level 19
setWindow(int type,
long windowStartMillis,
long windowLengthMillis,
PendingIntent operation)

 

setWindow: 上記setWindowにDirect Callbackが追加


1
2
3
4
5
6
7
//API level 24
setWindow (int type,
long windowStartMillis,
long windowLengthMillis,
String tag,
AlarmManager.OnAlarmListener listener,
Handler targetHandler)

 

setAlarmClock: Dozeモードでもアラームを出してくれるようです。


1
2
3
// API level 21
setAlarmClock (AlarmManager.AlarmClockInfo info,
PendingIntent operation)

 

また、その他に

cancel

設定したアラームの取り消し

setTime

ミリ秒での時間設定

setTimeZone

タイムゾーンの設定

などがあります

 

また、アラームに関する定数が幾つかあります。例えば、

ELAPSED_REALTIME

スリープ時間を含んだブートアップからの経過時間

ELAPSED_REALTIME_WAKEUP

ELAPSED_REALTIME に加えて、実機スリープ中では wake up してくれる

RTC

時刻

RTC_WAKEUP

RTCに加えて実機スリープ中では wake up してくれる

 

 

PendingIntent


 

PendingIntent は作成した Intent をタイミングを見て他のアプリケーションに渡す場合に使います。


1
2
3
4
// Intent のインスタンス生成
Intent indent = new Intent(getApplicationContext(), AlarmBroadcastReceiver.class);
// Broadcast にメッセージを送るための設定
PendingIntent pending = PendingIntent.getBroadcast(getApplicationContext(), 0, indent, 0);

 

getBroadcastの第2引数は requestCode です。PendingIntent が1つの場合は0で大丈夫ですが複数ある時は、この requestCode を使って Receiver 側で切り分けます

Ref: PendingIntent

http://developer.android.com/reference/android/app/PendingIntent.html

 

BroadcastReceiver


 

PendingIntent からの Intent を受け取りるクラスを新しく作ります。そこでアラームを受けトーストします。

 


1
2
3
4
5
6
public class AlarmBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Received ", Toast.LENGTH_LONG).show();
}
}

 

サンプルコード


 

これらの内容をふまえて実際にコードを組んでみましょう

 

WAKE_LOCK パーミッションとBroadcast の receiver を入れます。

AndroidManifest.xml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
..


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


<application
...
<activity
...
</activity>


<receiver android:name=".AlarmBroadcastReceiver"
android:process=":remote" />


</application>


</manifest>

 

ボタンをタップしてアラームをセットするようにします

MainAcrivity.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package your.package.name;


import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.util.Calendar;


public class MainActivity extends AppCompatActivity {


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


// 開始ボタン
Button button = this.findViewById(R.id.button1);
String str = "Alarm Start";
button.setText(str);


button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 時間をセットする
Calendar calendar = Calendar.getInstance();
// Calendarを使って現在の時間をミリ秒で取得
calendar.setTimeInMillis(System.currentTimeMillis());
// 5秒後に設定
calendar.add(Calendar.SECOND, 5);


//明示的なBroadCast
Intent intent = new Intent(getApplicationContext(),
AlarmBroadcastReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(
getApplicationContext(), 0, intent, 0);


// アラームをセットする
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
if(am != null){
am.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pending);


Toast.makeText(getApplicationContext(),
"Set Alarm ", Toast.LENGTH_SHORT).show();
}


}
});
}
}

 

アラームをBroadcastReceiver で受けます

AlarmBroadcastReceiver.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package your.package.name;


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;


public class AlarmBroadcastReceiver extends BroadcastReceiver {


@Override
public void onReceive(Context context, Intent intent) {
// toast で受け取りを確認
Toast.makeText(context, "Received ", Toast.LENGTH_LONG).show();
}
}

 

activity_main.xml


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">


<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="50dp"
android:textSize="18sp"/>


</LinearLayout>

 

サンプル動画


 

 

 

アラームを設定して開始

BroadcastReceiver で受け取るという簡単な例でした

次はアラームを通知できるようにしてみます

 

 

関連:

AlarmManagerをBroadcastRecieverと使う

Alarm を NotificationManager で通知する

Doze mode で AlarmManager の繰り返しアラームを実装するには

アプリの restart

 

References:

AlarmManager | Android Developers

BroadcastReceiver | Android Developers

PendingIntent | Android Developers

誤字脱字、意味不明で分からにゃイ、

などのご意見はこちらから mailフォーム

ブックマークしておくと便利です

アプリ開発が上達するお勧め


アプリ開発を始めたけどわからないところがあり、誰かに聞きたいけど周りにはそんな人はいない…あるいは、会社で働いていて日中そんなに時間をとれないなど、オンラインのプログラミングスクールがいいでしょう。

オンラインスクールは色々ありますが、以下の3つはAndroidが学習できる老舗スクールです。

댓글