【Android】Firebase Cloud Messagingを利用してプッシュ通知を実装する【Firebase】

FirebaseにAndroidアプリを追加する。Android

自作アプリ「TwitMorse 〜モールス信号でつぶやこう〜」のアクティブインストール数が75もあるわりに、モールス信号でメッセージを発信してくれる人が少なくてなんだかなぁと思っていた昨今。
ついにプッシュ通知を実装することにしました。通知が来ればユーザーさんもモールス信号でつぶやくようになるのでは?という仮説を実証するためです。

思えば通知機能の開発は会社づとめしていた頃に実装していただけで、個人で開発してリリースしているアプリでは使った事がありませんでした。



以前は通知の実装をするのに、会社側の制約があったりして、うっかりGoogle様のfirebaseなんて触ることは許されていなかったのですが、今はフリーの身。なんでもっと早く通知つくらなかったんだろうと思いながら、実際にFirebase Cloud Messagingによる通知が動くところまでこぎつけたので、その手順を書いていきます。

ちょっと手順的に詰まったりして長くなってしまうかもしれませんが、これで私のアプリのFCMは動きました、的な記録です。

Firebaseを利用した通知を実装する

Googleが提供するモバイル開発プラットフォーム「Firebase」を利用すれば、サクッと通知が実装できるらしい・・・ということでFirebaseを利用した手順をここでは書いていきます。

とりあえずFirebaseに登録を済ませて、Firebase Consoleにアクセスしましょう。

Firebaseにアプリを登録

Firebaseコンソールにアクセスできたら、「プロジェクトを追加」を選択
firebaseコンソールにてプロジェクトを追加

適当なプロジェクト名を入力します。ここではfirebase-sample-projectとします。

firebaseにプロジェクトを追加する

プロジェクトの作成手順の2番目では、既にGoogle Analyticsのアカウントを持っている場合デフォルトのまま次へ。ちなみにアナリティクスアカウントと紐付けることが推奨されていますので、持っていない人はアカウント開設すると良いです。
アナリティクスのアカウントを持っていない場合はスイッチをオフにして、次へ行くとすぐにプロジェクトができあがります。


Androidアプリ側とFirebaseを接続する

FirebaseにAndroidアプリを追加する。

プロジェクトのトップ画面。今回はAndroidアプリの通知を試したいのでドロイドくんのアイコンをクリックしてください。

Androidアプリ側の設定をしていく(Firebase上で)

Android パッケージ名 例アプリのニックネーム (省略可)デバッグ用の署名証明書 SHA-1(省略可)
jp.sub.takelab.twitmorusTwitMorse (省略可とありますが一応)省略可

省略可となっているところですが、あったほうがいいです。通知をテストしたい時に使えます。

デバッグ用の署名証明書 SHA-1の取得方法

下記を参照してください。

[Android] Android Studioで簡単なSHA-1発給。 | qiita.com/Dreamwalker

入力が終わったら「次へ」

androidアプリとfirebaseを接続する手順2

「google-services.jsonをダウンロード」をクリックし、google-services.jsonをダウンロード。

google-services.jsonは下記のようにAndroidプロジェクトのappディレクトリに配置します。

google-serives.jsonをappディレクトリに配置

続いて、Android StudioでFirebaseプロジェクトと接続したいプロジェクトを開きます。

shift shiftと素早く押して「build.gradle」を検索してエンター
プロジェクトルートのbuild.gradleに下記を追記

buildscript {
  repositories {
    // Check that you have the following line (if not, add it):
    google()  // ←これ GoogleのMavenリポジトリ
    //mavenCentral() // ←こいつ入れてるとfirebaseと疎通できなかった
  }
  dependencies {
    ...
    // Add this line
    classpath 'com.google.gms:google-services:4.3.2'// ←これ firebaseを使うのに必須
  }
}

allprojects {
  ...
  repositories {
    // Check that you have the following line (if not, add it):
    google()  // Google's Maven repository
    ...
  }
}

※ここで私はつまりました。
rootディレクトリのbuild.gradleのrepositories内にmavenCentral()の記述があったのですが、そいつが悪さをしているのか不明ですが、後の手順の「アプリを実行してインストールを確認」に進んでアプリを実行すると、いつまで経っても「アプリがサーバーと通信したかどうかを確認中です。」が終わらないという現象が起きていました。。。

build.gradle編集後、firebase側と疎通確認

mavenCentral()をコメントアウトしたらうまく疎通できました。原因は不明。。。

続いて、app/build.gradleにも追記

apply plugin: 'com.android.application'

// 中略

dependencies {
    // 中略 ...
    /////////////////
    // Firebase start
    implementation 'com.google.firebase:firebase-core:17.2.0'
    implementation 'com.google.firebase:firebase-messaging:20.0.0'
    // Firebase end
    /////////////////
    // 中略 ...
}
//一番下の行に下記を追加
apply plugin: 'com.google.gms.google-services'

Gradle syncが終わったら、「次へ」を選択。

「アプリを実行してインストールを確認」

下記状態になればOK

firebaseでアプリを実行してインストールを確認


アプリ側でFirebaseMessagingServiceを作る

アプリ側でsrc/main/java//内でFirebaseMessageingServiceを継承したクラスを作ります。

TwitMorseFirebaseMessageingService.kt

class TwitMorseFirebaseMessagingService: FirebaseMessagingService() {

    /**
     * ここの定数でバージョンごとにチャネルを管理するのはいかがなものかと思うが、一旦ここで管理する
     *
     **/
    companion object {
        private const val CHANNEL_ID1 = "jp.sub.takelab.twitmorus.service.fcm.firebase_notification1"
        private const val CHANNEL_ID2 = "jp.sub.takelab.twitmorus.service.fcm.firebase_notification2"
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        remoteMessage.data.also { data ->
            val title = data["title"]
            val message = data["message"]

            // Android O(8.0) 以上で通知を表示する場合はチャンネルIDを指定する必要があるので
            // 処理を分けます
            val builder = if (Build.VERSION_CODES.O <= Build.VERSION.SDK_INT) {
                NotificationCompat.Builder(this, CHANNEL_ID2)
            }
            else {
                NotificationCompat.Builder(this)
            }
            val notification = builder
                    .setSmallIcon(R.drawable.notification_twitmorse_white_gray) // アイコンは指定必須です
                    .setColor(ContextCompat.getColor(this, R.color.design_default_color_primary))
                    .setContentTitle(title)                 // 通知に表示されるタイトルです
                    .setContentText(message)                // 通知内容を設定します
                    .build()
            // 通知を表示します
            val nm = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
            nm.notify(0, notification)
        }
    }

    override fun onNewToken(instanceToken: String) {

        // テストで使用するため、ログにトークンを出力します
        Log.i("FCM Token", "token: $instanceToken")

        // 同時に通知の設定をここでしてしまいます
        val nm = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        // Android O(8.0) 以上で通知を使用する場合は通知チャンネルを作成する必要があります
        if (Build.VERSION_CODES.O <= Build.VERSION.SDK_INT) {
            var channel = nm.getNotificationChannel(CHANNEL_ID2)
            if (channel == null) {
                channel = NotificationChannel(
                        CHANNEL_ID2,
                        "プッシュ通知用のチャンネルです",
                        NotificationManager.IMPORTANCE_HIGH)
                nm.createNotificationChannel(channel)
            }
        }

    }
}

Log.i("FCM Token", "token: $instanceToken")という部分がありますが、これは後々テストするために活躍します。

マニフェストファイルの追記も必要です。

AndroidManifest.xml

<manifest>
    <application>
        ...
        ...
        ...
        <!-- for Notification by firebase messaging-->
        <service
            android:name=".service.TwitMorseFirebaseMessagingService"
            android:exported="false">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
        ...
        ...
        ...
    </application>
</manifest>

追加したserviceクラスを登録しておきましょう。

参考資料

AndroidでFirebaseを使ったPush通知(FCM)を実装する | aizulab

ここまで来たら、通知のテストが発射可能です。早速runしてアプリをエミュレータか実機にインストールしておきましょう。

Firebase Notificationの動作確認

firebase consoleよりCloud Messagingを選択

Firebaseコンソールより、Cloud Messagingを開いてください。

firebase cloud messagingによる通知テスト

通知タイトルと通知テキストには適当な値を入れます。なんでもいいですが、ミスして本番環境に通知が飛んでもいいような文面が無難です。
気をつけてください。

そして、「テスト メッセージを送信」を押すと

fcmテスト通知

「FCM登録トークンを追加」の行に先のFirebaseMessagingServiceを継承したクラスに入れたLog.i("FCM Token", "token: $instanceToken")でLogcatを覗いて、FCM(Firebase Cloud Messaging)のトークンを取得します。

2019-09-29 17:36:00.954 9093-9280/? I/FCM Token: token: 
endVkxqIBPA:APA91bH-nBKP0eB8Uk7e9U9Y8uCjqnU_mJyiR_XcBklrcD7iQseUcS-zd5L98_7DKeM60LcUOpnL1lTBEVbbmaJJgQX4vJkEJMyMX_8qgmMedbqenEMgZSLF8LkunXAKRXe9UYfnli9r

↑こいつを「FCM登録トークンを追加」の行に入れて、出てきた+ボタンを押してください。
そして、「テスト」をクリックすると・・・

Firebase Cloud Messagingのテストを打つ

ご覧ください!このエミュレータだけにテスト用の通知が出ました!!

タップすると、MainActivityが起動します(デフォルトでそうなるらしい)。

まだまだ課題はあるが、とりあえず一旦ここまで

この手順通りにやってうまくいく人がどれだけいるかわかりませんが、Android開発初心者の方々が読めるように書いてみました。
私自身、実際にFirebaseをまともにいじるのは今回が初めてでした。特にFirebaseとAndroidアプリとの疎通がうまく行かず時間がかかってしまいました。リポジトリの依存関係が原因??なのか分からないですが、とりあえず書きたかった解決方法も書きました。

まだまだ通知周りには課題が残っています。

  • 通知のアイコンが白い四角(□)になってしまう

→ 2019年10月5日に解消:【Kotlin】通知のアイコンが白い四角(□)になってしまう問題の修正【Firebase】

  • アプリが起動している時と起動していない時で通知のステータスバーへの表示が変わる
  • 通知をタップした時にFirebase Consoleで開封としてカウントされていない

などなど、まだバグが残っています。これから一個ずつ解決していきたいと思います。

というわけで、TwitMorse 〜モールス信号でつぶやこう〜に通知機能が追加できたので、バグは残っていますが早速リリースしてどんな事が起きるか見てみたいと思います。

モールスのつぶやきが増えるといいなー。


参考資料

コメント

タイトルとURLをコピーしました