1
0

More than 3 years have passed since last update.

Codelabsの通知機能の実装をViewModelを使って書き換えてみた

Last updated at Posted at 2021-03-27

はじめに

Codelabs タスク1:基本的な通知を作成するを参考に通知機能を実装してみた。
notification.gif

通知機能の実装ポイント

①通知チャネルを作成する

  • チャネルIDを用意
  • 通知チャネルのカスタマイズ初期設定(APIレベル26以上に対して)
    • チャネルの設定名称
    • 通知の優先度(他にも通知が複数あったときの表示位置の優先度)
    • バイブ、LEDの色設定
    • チャネルの説明文
  • 注意事項
    • Android8.0(APIレベル26)より古いデバイスはカスタマイズできない。
    • Android8.0(APIレベル26)以上は通知チャネルを作成しないとクラッシュする。

通知チャネル画面を比較する

Android7.0(APIレベル24) Android10.0(APIレベル29)
スクリーンショット 2021-03-17 17.58.47.png スクリーンショット 2021-03-17 17.59.53.png

通知チャネルのカスタマイズ画面(APIレベル26以上)

②通知を作成する

  • 通知IDを用意
  • 通知する内容を設定
    • タイトル
    • 本文
    • アイコン
    • タップしたときの処理
    • 通知の優先度(API25以下に対して)
    • バイブ、LEDの色設定(API25以下に対して)

③通知を送信する

ボタンがクリックされた時に②で設定した通知を送信させる

実装

layout

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_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            android:onClick="@{(v) -> viewModel.sendNotification()}"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

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;
    }
}

ViewModel

NotificationViewModel.java
public class NotificationViewModel {

    // チャネル 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 void setView(NotificationView view) {
        this.view = view;
    }

    // 通知チャネル作成(ユーザーが通知設定をカスタマイズできるようにする)
    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() {

        // MainActivityを起動してくれる通知のコンテンツインテントを取得
        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());
    }
}

おわりに

次回は通知の更新、キャンセルを紹介

参考サイト

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0