前回の続き
タスク2:通知を更新またはキャンセルするを参考に通知機能を実装してみた。
update | cancel |
---|---|
![]() |
![]() |
実装
layout
android:enabled
でボタン操作をコントロール
true
のときボタンが押せる
false
のときボタンが押せない
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout 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"
tools:context=".MainActivity">
<data>
<variable
name="viewModel"
type="com.example.samplenotification.NotificationViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/notify"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Notify Me!"
app:layout_constraintBottom_toTopOf="@+id/update"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:enabled="@{viewModel.sendButtonEnabled}"
android:onClick="@{(v) -> viewModel.sendNotification()}"/>
<Button
android:id="@+id/update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Update Me!"
app:layout_constraintBottom_toTopOf="@+id/cancel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/notify"
android:enabled="@{viewModel.updateButtonEnabled}"
android:onClick="@{(v) -> viewModel.updateNotification()}"/>
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cancel Me!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/update"
android:enabled="@{viewModel.cancelButtonEnabled}"
android:onClick="@{(v) -> viewModel.cancelNotification()}"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
ViewModel
ボタンコントロールの設定
ViewModel抜粋
public class NotificationViewModel extends BaseObservable {
public boolean sendButtonEnabled = true; // 起動時はsendボタンのみ押せるようにする
public boolean updateButtonEnabled;
public boolean cancelButtonEnabled;
@Bindable public boolean isSendButtonEnabled() {
return sendButtonEnabled;
}
public void setSendButtonEnabled(boolean sendButtonEnabled) {
this.sendButtonEnabled = sendButtonEnabled;
notifyPropertyChanged(BR.sendButtonEnabled);
}
@Bindable public boolean isUpdateButtonEnabled() {
return updateButtonEnabled;
}
public void setUpdateButtonEnabled(boolean updateButtonEnabled) {
this.updateButtonEnabled = updateButtonEnabled;
notifyPropertyChanged(BR.updateButtonEnabled);
}
@Bindable public boolean isCancelButtonEnabled() {
return cancelButtonEnabled;
}
public void setCancelButtonEnabled(boolean cancelButtonEnabled) {
this.cancelButtonEnabled = cancelButtonEnabled;
notifyPropertyChanged(BR.cancelButtonEnabled);
}
}
更新通知の定義
ViewModel抜粋
public void updateNotification() {
// 画像ファイルをビットマップに変換。
// 外部に既に存在している画像ファイルを読み込むには「BitmapFactory」クラスを利用する。
Bitmap androidImage = BitmapFactory.decodeResource(view.getContext().getResources(), R.drawable.mascot_1);
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
// 通知ビルダーの設定内容を上書きする
// BigPictureStyleは、NotificationCompat.Styleのサブクラス。通知の代替レイアウトを提供する。
notifyBuilder.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(androidImage)
.setBigContentTitle("通知更新!"))
.setContentText("本文が更新されました");
// 通知を送信する
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
// updateボタンを押せなくさせる
setUpdateButtonEnabled(false);
}
キャンセルの定義
ViewModel抜粋
public void cancelNotification() {
// IDに紐づく通知をキャンセルする
mNotifyManager.cancel(NOTIFICATION_ID);
// 各ボタンのコントロール
setSendButtonEnabled(true);
setUpdateButtonEnabled(false);
setCancelButtonEnabled(false);
}
ViewModel全文
NotificationViewModel.java
public class NotificationViewModel extends BaseObservable {
// チャネル ID 全てのチャネルはパッケージ内で一意のIDに関連付ける
private static final String PRIMARY_CHANNEL_ID = "primary_notification_channel";
// PendingIntentに渡す通知id(requestCode)。 通知作成,更新または削除する場合に必要になるため、通知IDは必ず保存する。
private static final int NOTIFICATION_ID = 0;
// 通知処理を管理してくれるオブジェクト
private NotificationManager mNotifyManager;
private NotificationView view;
public boolean sendButtonEnabled = true;
public boolean updateButtonEnabled;
public boolean cancelButtonEnabled;
public void setView(NotificationView view) {
this.view = view;
}
@Bindable public boolean isSendButtonEnabled() {
return sendButtonEnabled;
}
public void setSendButtonEnabled(boolean sendButtonEnabled) {
this.sendButtonEnabled = sendButtonEnabled;
notifyPropertyChanged(BR.sendButtonEnabled);
}
@Bindable public boolean isUpdateButtonEnabled() {
return updateButtonEnabled;
}
public void setUpdateButtonEnabled(boolean updateButtonEnabled) {
this.updateButtonEnabled = updateButtonEnabled;
notifyPropertyChanged(BR.updateButtonEnabled);
}
@Bindable public boolean isCancelButtonEnabled() {
return cancelButtonEnabled;
}
public void setCancelButtonEnabled(boolean cancelButtonEnabled) {
this.cancelButtonEnabled = cancelButtonEnabled;
notifyPropertyChanged(BR.cancelButtonEnabled);
}
// 通知チャネル作成(ユーザーが通知設定をカスタマイズできるようにする)
public void createNotificationChannel() {
mNotifyManager = (NotificationManager) view.getContext().getSystemService(NOTIFICATION_SERVICE);
// Android 8.0(APIレベル26)より古いデバイスはカスタマイズできない。逆にAndroid8.0(APIレベル26)以上は作成しないとクラッシュする。
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(PRIMARY_CHANNEL_ID, "お知らせ", NotificationManager.IMPORTANCE_HIGH);
// 通知機能の初期設定
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setDescription("お知らせの説明");
mNotifyManager.createNotificationChannel(notificationChannel);
}
}
// 送信する通知内容を定義
private NotificationCompat.Builder getNotificationBuilder() {
PendingIntent notificationPendingIntent = view.getNotificationContentIntent(NOTIFICATION_ID);
// 通知ビルダー(チャネル ID の指定を必要とするコンストラクタ)の初期設定をする
NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(view.getContext(), PRIMARY_CHANNEL_ID)
.setContentTitle("通知されました")
.setContentText("ここは本文です")
.setSmallIcon(R.drawable.ic_android) // 通知アイコンの設定
.setContentIntent(notificationPendingIntent) // ユーザーが通知をタップしたときに起動するインテント
.setAutoCancel(true) // ユーザーが通知をタップしたときに通知を閉じる
// 以下、Android 8.0(APIレベル26)より古いデバイスに対しての設定
.setPriority(NotificationCompat.PRIORITY_HIGH) // 通知の優先度を設定。通知が複数あったとき優先度の高い通知から上に並べられる
.setDefaults(NotificationCompat.DEFAULT_ALL); // 通知の音、バイブレーション、LEDの色パターンをデフォルト値に設定
return notifyBuilder;
}
public void sendNotification() {
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
setSendButtonEnabled(false);
setUpdateButtonEnabled(true);
setCancelButtonEnabled(true);
}
public void updateNotification() {
// ビットマップに変換。 外部に既に存在している画像ファイルを読み込むには「BitmapFactory」クラスを利用する。
Bitmap androidImage = BitmapFactory.decodeResource(view.getContext().getResources(), R.drawable.mascot_1);
NotificationCompat.Builder notifyBuilder = getNotificationBuilder();
// 通知ビルダーの設定内容を上書きする
// BigPictureStyleは、NotificationCompat.Styleのサブクラス。通知の代替レイアウトを提供する。
notifyBuilder.setStyle(new NotificationCompat.BigPictureStyle()
.bigPicture(androidImage)
.setBigContentTitle("通知更新!"))
.setContentText("本文が更新されました");
mNotifyManager.notify(NOTIFICATION_ID, notifyBuilder.build());
setUpdateButtonEnabled(false);
}
public void cancelNotification() {
mNotifyManager.cancel(NOTIFICATION_ID);
setSendButtonEnabled(true);
setUpdateButtonEnabled(false);
setCancelButtonEnabled(false);
}
}
Interface(前回と同じ)
NotificationView
public interface NotificationView {
PendingIntent getNotificationContentIntent(int notificationId);
Context getContext();
}
Activity(前回と同じ)
MainActivity.java
public class MainActivity extends AppCompatActivity implements NotificationView{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
NotificationViewModel notificationViewModel = new NotificationViewModel();
// ViewModelにActivityのViewを紐付ける
notificationViewModel.setView(this);
// xmlのviewModelにNotificationViewModelを紐付ける
binding.setViewModel(notificationViewModel);
// 通知チャネル作成
notificationViewModel.createNotificationChannel();
}
// PendingIntentを使用すると、Android通知システムがコードに代わって割り当てられたアクションを実行してくれる。
@Override
public PendingIntent getNotificationContentIntent(int notificationId) {
Intent notificationIntent = new Intent(this, MainActivity.class);
// PendingIntentの作成にはコンテンツインテント(アクティビティを起動するインテント)と通知idが必要
PendingIntent notificationPendingIntent = PendingIntent.getActivity(this,
notificationId, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
return notificationPendingIntent;
}
@Override
public Context getContext() {
return this;
}
}
参考サイト