通知(Notification)
参考1: 通知
参考2: 通知チャネル
参考3: 研修10日目
ホーム画面
の通知領域
に通知アイコン
を表示したり、通知ドロワー
に通知メッセージ
を表示したりできる機能。
通知
はバックグラウンド処理
で実行されるため、バックグラウンド処理
を行うサービスクラス
(=Service
クラスを継承するクラス)で管理する。
通知情報
に関するデータはNotificationCompat.Builder
を通じてNotification
オブジェクトによって管理され、
通知方法
に関するデータは通知チャネル
(=NotificationChannel
オブジェクト)に格納され、通知チャネル
はNotificationManager
によって管理される。
また、通知
(=Notification
オブジェクト)はNotificationManagerCompat
オブジェクトによって実行される。
通知領域と通知アイコン
通知ドロワーと通知メッセージ
NotificationCompat.Builder
Notification
オブジェクトのファクトリクラスであり、
NotificationCompat
クラス内で定義されたクラス(=ネストクラス
)。
Notification
通知
のアイコン
・タイトル
・メッセージ
など、通知情報
に関するデータを格納するクラス。
通知チャネル(NotificationChannel)
通知
の重要度
・通知音
・バイブレーションパターン
など、通知方法
に関するデータを、チャネル毎にまとめて管理できる機能。
NotificationManager
通知方法
に関する各種データを格納した通知チャネル
(=NotificationChannel
オブジェクト)と、
通知情報
に関するデータを格納したNotification
オブジェクトを管理するクラス。
NotificationManagerCompat
通知
を実行するメソッドを定義するクラス。
NotificationManagerCompat
オブジェクトは、独自に再定義したNotificationManager
オブジェクトを保持するサービスクラス
で管理される。
通知の実装
参考1: 通知
参考2: 通知の作成
通知
機能を実装する手順は、以下の通り。
通知チャネル
(=NotificationChannel
オブジェクト)の生成NotificationManager
オブジェクトの取得、通知チャネル
のセットNotificationCompat.Builder
オブジェクトの生成、通知情報
の定義Notification
オブジェクトの生成NotificationManagerCompat
オブジェクトを用いて通知を表示
通知チャネルの生成
通知方法
に関するデータをまとめる通知チャネル
は、サービス
の初期化時に実行されるonCreate()
ブロック内で生成する。
なお、サービスクラス
では、親であるService
クラスで定義されたメソッドのオーバーライド
時に、親メソッド
を呼び出す必要がない。
また、チャネルID
はサービスクラス
で不変であるため、クラス定数
としてcompanion object
ブロックで定義する。
定義
// 通知チャネルの生成
NotificationChannel(
id: String!,
name: CharSequence!,
importance: Int
)
// パラメータ
// id: パッケージ内で一意の、通知チャネルの識別ID(String型)
// name: ユーザに表示される通知チャネル名
// importance: 通知チャネルの重要度
// -> NotificationManagerクラス定数を利用
通知チャネルの重要度を表すNotificationManagerクラス定数
重要度 | 定数名 | 内容 |
---|---|---|
高 | IMPORTANCE_HIGH |
通知音とポップアップ 値: 4
|
↑ | IMPORTANCE_DEFAULT |
通知音のみ 値: 3
|
IMPORTANCE_LOW |
スリープ画面最上部への通知メッセージ ※通知アイコンあり 値: 2
|
|
↓ | IMPORTANCE_MIN |
スリープ画面下部への通知メッセージ ※通知アイコンなし 値: 1
|
低 | IMPORTANCE_NONE |
非通知 値: 0
|
サンプルコード
class SoundManageService : Service() {
// クラス定数
companion object {
private const val CHANNEL_ID = "soundmanagerservice_notification_channel"
}
...
// サービスの初期化時に実行する処理
// <- 親クラスのonCreate()メソッドの呼び出しは不要
override fun onCreate() {
...
// 通知チャネル名
val name = getString(R.string.notification_channel_name)
// 通知チャネルの重要度
// -> NotificationManagerのクラス定数を利用
val importance = NotificationManager.IMPORTANCE_DEFAULT
// 通知チャネル
val channel = NotificationChannel(CHANNEL_ID, name, importance)
...
}
...
}
NotificationManagerオブジェクトの取得・通知チャネルのセット
NotificationManager
はOSレベル(システムレベル)
で既に提供されているサービスオブジェクト
であるため、Context.getSystemService()
メソッドを用いて取得する。
また、独自に作成した通知チャネル
をNotificationManager
に管理させるには、NotificationManager
内で通知チャネル
を再生成する必要がある。
定義
// サービスオブジェクトの取得
fun <T: Any!> Context.getSystemService(serviceClass: Class<T>): T
// パラメータ
// serviceClass: OSレベル(システムレベル)で提供されるサービスオブジェクトのJavaクラス名
// または
// Contextクラス定数(後述)
// NotificationManagerに通知チャネルをセット
NotificationManager.createNotificationChannel(
channel: NotificationChannel
): Unit
// channel: 通知チャネルオブジェクト
サービスオブジェクトを表すContextクラス定数
Javaクラス名
が使用できるサービスオブジェクト
は限られているため、その場合はContext
クラスのクラス定数
を利用する。
サンプルコード
class SoundManageService : Service() {
...
// サービスの初期化時に実行する処理
// <- 親クラスのonCreate()メソッドの呼び出しは不要
override fun onCreate() {
...
// 通知チャネル
val channel = NotificationChannel(CHANNEL_ID, name, importance)
// NotificationManagerオブジェクトの取得
val manager = getSystemService(NotificationManager::class.java)
// 通知チャネルをセット
manager.createNotificationChannel(channel)
}
...
}
通知情報の定義
参考: NotificationCompat.Builder
通知情報
に関するデータは、Notification
オブジェクトのファクトリクラス
であるNotificationCompat.Builder
に格納(=セット
)する。
Notification
オブジェクトに格納されるデータは「Notification
オブジェクトが生成された時点でNotificationCompat.Builder
オブジェクトが持っているデータ」であるため、
Notification
オブジェクトを生成する前に通知情報
に関するデータをNotificationCompat.Builder
オブジェクトに格納しておく必要がある。
定義
// NotificationCompat.Builderオブジェクトの生成
NotificationCompat.Builder(
@NonNull context: Context,
@NonNull channelId: String
)
// context: NotificationCompat.Builderオブジェクトを生成する
// サービスクラスオブジェクト(=コンテキスト)
// channelId: Notificationオブジェクトを連携させる通知チャネルID
// 通知エリアに表示するアイコンの格納
@NonNull
NotificationCompat.Builder.setSmallIcon(
icon: Int
): NotificationCompat.Builder
// パラメータ
// icon: アイコンのID(R値)
// 通知ドロワーに表示するタイトル
@NonNull
NotificationCompat.Builder.setContentTitle(
@Nullable title: CharSequence?
): NotificationCompat.Builder
// パラメータ
// title: タイトルを表すCharSequence型文字列
// -> CharSequence: String型やStringBuilder型で実装されるインタフェース
// => String型やStringBuilder型の文字列が利用可能
// 通知ドロワーに表示するメッセージ
@NonNull
NotificationCompat.Builder.setContentText(
@Nullable text: CharSequence?
): NotificationCompat.Builder
// パラメータ
// text: メッセージを表すCharSequence型文字列
サンプルコード
// クラス定数
companion object {
private const val CHANNEL_ID = "soundmanagerservice_notification_channel"
}
// Notificationオブジェクトを生成するBuilderオブジェクト
val builder = NotificationCompat.Builder(this@SoundManageService, CHANNEL_ID)
// 通知エリアに表示するアイコン
builder.setSmallIcon(android.R.drawable.ic_dialog_info)
// 通知ドロワーに表示するタイトル
// -> Context.getString(resId:)メソッドを用いてCharSequence型文字列を取得
builder.setContentTitle(getString(R.string.msg_notification_title_finish))
// 通知ドロワーに表示するメッセージ
builder.setContentText(getString(R.string.msg_notification_text_finish))
Notificationオブジェクトの生成
Notification
オブジェクトは、そのファクトリクラス
であるNotificationCompat.Builder
クラスのbuild()
メソッドを用いて生成する。
定義
@NonNull
NotificationCompat.Builder.build(): Notification
サンプルコード
// Notificationオブジェクトを生成するBuilderオブジェクト
val builder = NotificationCompat.Builder(this@SoundManageService, SoundManageService.CHANNEL_ID)
... // 通知情報に関するデータの格納
// Notificationオブジェクト
val notification = builder.build()
NotificationManagerCompatによる通知の実行
通知
はNotificationManagerCompat
のnotify()
メソッドを用いて実行する。
なお、NotificationManagerCompat
オブジェクトは、独自に再定義したNotificationManager
オブジェクトを管理するサービスクラス
で管理されるため、
NotificationManagerCompat
クラスのfrom()
メソッドを用いてサービスクラス
から取得する必要がある。
定義
// サービスクラスがもつNotificationManagerCompatオブジェクトの取得
@NonNull
NotificationManagerCompat.from(
@NonNull context: Context
): NotificationManagerCompat
// パラメータ
// context: NotificationManagerを管理するサービスクラスオブジェクト(=コンテキスト)
// 通知の実行
NotificationManagerCompat.notify(
id: Int,
@NonNull notification: Notification
): Unit
// パラメータ
// id: アプリ内で一意となる、Notificationオブジェクトの識別ID
// notification: Notificationオブジェクト
サンプルコード
// Notificationオブジェクトを生成するBuilderオブジェクト
val builder = NotificationCompat.Builder(this@SoundManageService, CHANNEL_ID)
... // NotificationCompat.Builderに通知情報に関するデータをセット
// Notificationオブジェクトの生成
val notification = builder.build()
// サービスクラスからNotificationManagerCompatオブジェクトを取得
val manager = NotificationManagerCompat.from(this@SoundManageService)
// 通知を実行
manager.notify(100, notification)
アクティビティを起動する通知の実装
参考1: 通知からアクティビティを起動する
参考2: 研修3日目
アクティビティ
間の画面遷移を実現するインテント
を利用したPendingIntent
を用いて、通知ドロワー
からアクティビティ
を起動することができる。
通知ドロワー
からアクティビティ
を起動する手順は、以下の通り。
- 起動先
アクティビティ
の情報を保持するIntent
オブジェクトの生成- 起動先
アクティビティ
に値を渡す必要があれば、Intent
オブジェクトにデータを格納Intent
オブジェクトを保持するPendingIntent
オブジェクトの生成NotificationCompat.Builder
オブジェクトにPendingIntent
オブジェクトを格納(=セット
)マニフェストファイル
(=AndroidManifest.xml
)にフォアグラウンドサービス
のパーミッション
を記述Notification
オブジェクトを生成し、サービス
をフォアグラウンド
で実行
インテント(Intent)
アクティビティ
・フラグメント
・サービス
間の橋渡し役を担うクラス。
遷移元
と遷移先
の情報をもつ。
PendingIntent
サービスオブジェクト
などの外部アプリケーション
に対して、インテント
の実行権限(=トークン
)を与えるメソッドを定義するクラス。
PendingIntent
はあくまで通知
(=Notification
オブジェクト)などからインテント
を実行できる権限に過ぎず、ユーザ操作
によって実行しない(=保留
する)ことも選択できるため、PendingIntent
と命名された。
IntentとPendingIntent
Intent
はアクティビティ
・フラグメント
・サービス
の起動を行うオブジェクト
であり、
PendingIntent
は外部アプリケーション
に対するインテント
の実行権限(=トークン
)を指す。
Intentオブジェクトの生成
PendingIntent
は外部アプリケーション
に対するアクティビティ
・サービス
の起動権限を指すが、
起動先アクティビティ・サービス
の情報はIntent
オブジェクトが保持するため、Intent
オブジェクトを作成する。
定義
Intent(packageContext: Context!, cls: Class<*>!)
// パラメータ
// packageContext: 起動元コンテキスト
// cls: Javaクラス化した起動先コンテキスト
// -> KotlinのクラスをJavaに変換する場合は、"<Kotlinクラス名>::class.java"と記述
サンプルコード
// 起動先アクティビティを指定するIntentオブジェクトの生成
val intent = Intent(this@SoundManageService, MainActivity::class.java)
Intentオブジェクトとのデータのやり取り
参考: 研修6日目(Bundle)
起動先
に対して起動元
から値を渡す場合は、Intent
クラスのputExtra()
メソッドを用いてデータを格納する。
また、渡す値がキー
と値
をもつMap
型のデータ構造(=Bundle
オブジェクト)である場合は、putExtras()
メソッドを用いてIntent
オブジェクトにデータを格納する。
起動先
で値を受け取る際は、引数name
にキー
を指定したget<T>Extra(name:defaultValue:)
メソッドを用いて値を取得する。
定義
// -- データの格納 --
// Intentオブジェクトへのデータ格納(起動元, Bundle型以外)
Intent.putExtra(name: String!, value: <T>): Intent
// パラメータ
// name: データ取得時に必要となるキー
// value: 起動先アクティビティ・サービスに渡す値
// Intentオブジェクトへのデータ格納(起動元, Bundle型)
Intent.putExtras(extras: Bundle): Intent
// パラメータ
// extras: 起動先アクティビティ・サービスに渡すBundleオブジェクト
// -- データの取得 --
// Intentオブジェクトからのデータ取得(起動先, Bundle型・配列以外)
Intent.get<T>Extra(name: String!, defaultValue: <T>): <T>
// パラメータ
// name: 取得する値のキー
// defaultValue: 対象のデータが存在しない場合に返される値
// Intentオブジェクトからのデータ取得(起動先, 配列)
Intent.get<T>ArrayExtra(name: String!): <T>Array?
// パラメータ
// name: 取得する配列データのキー
// Intentオブジェクトからのデータ取得(起動先, Bundle型)
Intent.getExtras(): Bundle?
サンプルコード
// 起動先アクティビティを指定するIntentオブジェクトの生成
val intent = Intent(this@SoundManageService, MainActivity::class.java)
// Intentオブジェクトにデータを格納
intent.putExtra("fromNotification", true)
// Intentオブジェクトからデータを取得
// <- アクティビティクラスはIntentオブジェクトをintentプロパティとして保持
val fromNotification = intent.getBooleanExtra("fromNotification", false)
PendingIntentオブジェクトの生成
PendingIntent
オブジェクトを生成するメソッドは、起動先オブジェクト
によって異なる。
起動先オブジェクト
がアクティビティ
である場合はgetActivity()
メソッドを、
サービス
である場合はgetService()
メソッドを用いる。
定義
// 起動先オブジェクトがアクティビティである場合
PendingIntent.getActivity(
context: Context!,
requestCode: Int,
intent: Intent!,
flags: Int
): PendingIntent!
// パラメータ
// context: 起動元コンテキスト
// requestCode: コンポーネントの識別番号
// <- 複数のコンポーネントからPendingIntentを利用する場合に利用
// intent: Intentオブジェクト
// flags: OS内にPendingIntentオブジェクトが残っている場合の処理フラグ
// -> PendingIntentクラス定数を利用
PendingIntentオブジェクトが重複した場合の処理を表すPendingIntentクラス定数
定数名 | 内容 |
---|---|
FLAG_ONE_SHOT |
既存オブジェクトの破棄 新しいオブジェクトの生成 |
FLAG_NO_CREATE |
既存オブジェクトの再利用 ※既存オブジェクトが存在しない場合は null
|
FLAG_CANCEL_CURRENT |
最初に生成されたオブジェクトの利用 |
FLAG_UPDATE_CURRENT |
既存オブジェクトの再利用extra データのみ置換 |
サンプルコード
// アクティビティを起動するPendingIntentオブジェクト
val stopServiceIntent = PendingIntent.getActivity(
this@SoundManageService,
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT
)
PendingIntentオブジェクトのセット
PendingIntent
オブジェクトを起動するのはNotification
オブジェクトであるが、
Notification
オブジェクトを生成するのはNotificationCompat.Builder
オブジェクトであるため、
NotificationCompat.Builder
オブジェクトにPendingIntent
オブジェクトをセットする。
なお、タップ
された通知
を自動的に消去する場合はNotificationCompat.Builder
のsetAutoCancel()
メソッドの引数にtrue
を指定する。
定義
// PendingIntentオブジェクトのセット
@NonNull
NotificationCompat.Builder.setContentIntent(
@Nullable intent: PendingIntent?
): NotificationCompat.Builder
//パラメータ
// intent: 最終的にNotificationオブジェクトにセットする
// PendingIntentオブジェクト
// 通知タップ時の通知ドロワーへの非表示フラグの変更
@NonNull
NotificationCompat.Builder.setAutoCancel(
autoCancel: Boolean
): NotificationCompat.Builder
// パラメータ
// autoCancel: 通知がタップされた場合の通知ドロワーへの非表示フラグ
// -> true: タップ時に通知ドロワーから削除
// false: タップ時に通知ドロワーに残置
サンプルコード
// Notificationオブジェクトを作成するBuilderオブジェクト
val builder = NotificationCompat.Builder(this@SoundManageService, CHANNEL_ID)
// 起動先アクティビティを指定するIntentオブジェクトの生成
val intent = Intent(this@SoundManageService, MainActivity::class.java)
// アクティビティを起動するPendingIntentオブジェクト
val stopServiceIntent = PendingIntent.getActivity(
this@SoundManageService,
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT
)
// BuilderにPendingIntentオブジェクトをセット
builder.setContentIntent(stopServiceIntent)
// タップされた通知メッセージを自動的に消去
builder.setAutoCancel(true)
マニフェストファイルへのパーミッションの追記
参考: 研修10日目(バックグラウンド処理)
通知
を含むサービス
は本来バックグラウンド処理
で動作するが、PendingIntent
を用いてユーザ操作
を受け付ける場合はフォアグラウンド処理
で動作させる必要がある。
ここで、サービス
をフォアグラウンド処理
で動作させる場合は、マニフェストファイル
(=AndroidManifest.xml
)にパーミッション
を追記する必要がある。
フォアグラウンド処理
アクティビティ
から独立したサービス
によってメインスレッド
上で実行される、ユーザから直接認識され、ユーザによって操作を受ける処理。
サンプルコード
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
...
</manifest>
サービスをフォアグラウンドで起動
アクティビティ
の起動をユーザ操作
によって行うため、アクティビティ
を起動する通知
を実行するサービスクラス
は、Service
クラスのstartForeground()
メソッドを用いて起動する。
定義
Service.startForeground(
id: Int,
notification: Notification!
): Unit
// パラメータ
// id: アプリ内で一意となる、Notificationオブジェクトの識別番号
// notification: 通知するNotificationオブジェクト
サンプルコード
// Notificationオブジェクトの生成
val notification = builder.build()
// サービスのフォアグラウンド実行
startForeground(200, notification)