AndroidでFCM(Firebase Cloud Messaging)を使ったpush通知を実装する方法です。
FCMの前身であるGCM(Google Cloud Messaging)が2019年4月に廃止されるとのことなのでこれからはFCMを使いましょう!
参考:https://developers-jp.googleblog.com/2018/04/time-to-upgrade-from-gcm-to-fcm.html
言語はkotlinです。
動作環境は以下のとおりです。
mac High Sierra 10.13.6
Android Studio 3.2
targetSdkVersion:28
compileSdkVersion:28
kotlin:1.2.71
Firebaseにプロジェクトを登録
Firebaseのコンソールへログインしてプロジェクトを登録します。(https://console.firebase.google.com/)
プロジェクトを追加したらoverviewからアプリを登録します。(今回はAndroid)
ここでダウンロードできる「google-services.json」が後で必要になるのでどこかに保存しておいてください。
Firebaseの導入
さっきfirebaseコンソールでダウンロードしてきたgoogle-services.jsonを/app直下に入れます。
gradleにライブラリを追加(バージョンは2018/11/20時点で最新のもの)
・projectレベル
1 2 3 | dependencies { classpath 'com.google.gms:google-services:4.0.1' } |
・appレベル
1 2 3 4 5 | dependencies { implementation 'com.google.firebase:firebase-messaging:17.3.4' } apply plugin: 'com.google.gms.google-services' |
実装例
Firebaseの公式に記載されている方法はバージョン17.1.0から非推奨になってます。
参考:https://qiita.com/taki4227/items/9d292c3badd2c4015061
なのでこちらにも記載されているようにFirebaseMessagingServiceクラスを使います。
今回は送信されてきたjsonのtitleとbodyをそれぞれ通知エリアの「タイトル」と「テキスト」に表示させてます。
メソッドは新しいトークンが生成された時の「onNewToken」、プッシュ通知を受信する「onMessageReceived」と通知エリアに表示するための処理も実装します。
また、Android8(Oreo)以上はチャンネルの設定をしなければ表示されないのでその処理も書きます。
ちなみにですがヘッドアップ通知(上から小さいウインドウが出てくる)をするにはbuilderとチャンネルの優先度と通知を最大にして音か振動のいずれかを出す必要があります。
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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | class SampleListenerService: FirebaseMessagingService() { private val TAG = javaClass.simpleName // 新しいトークンが生成された時の処理 override fun onNewToken(p0: String?) { super.onNewToken(p0) Log.d(TAG, "onNewToken token:$p0") // サーバにトークンを送信する処理を書く // channelidを設定 addChannelId() } // レシーバー override fun onMessageReceived(message: RemoteMessage?) { super.onMessageReceived(message) Log.d(TAG, "onMessageReceived token:${message?.data}") // jsonからタイトルと本文を取得 val title = message?.data?.get("title").toString() val text = message?.data?.get("body").toString() // 通知エリア表示設定 sendNotification(title,text) } private fun sendNotification(title: String, text: String) { // 通知エリアから遷移する際のアクティビティを指定 val intent = Intent(this, MainActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) // 一度だけ遷移する val pendingIntent = PendingIntent.getActivity(this,0, intent, PendingIntent.FLAG_ONE_SHOT) // 通知メッセージのスタイルを設定(改行表示に対応) val inboxStyle = NotificationCompat.InboxStyle() val messageArray = text.split("\n") for (msg in messageArray) { inboxStyle.addLine(msg) } // 通知音を設定 val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) // 通知を作成 val notificationBuilder = NotificationCompat.Builder(this,resources.getString(R.string.channel_id)) .setContentTitle(title) .setContentText(text) // ステータスバーに表示されるアイコン .setSmallIcon(R.mipmap.ic_launcher_round) // 通知エリアに表示されるアイコン .setLargeIcon(BitmapFactory.decodeResource(resources,R.mipmap.ic_launcher)) // 上で設定したpendingIntentを設定 .setContentIntent(pendingIntent) // メッセージを纏める時に表示するテキスト .setStyle(inboxStyle.setSummaryText("more")) // タップしたら自動で閉じるようにする .setAutoCancel(true) // 優先度を最大 .setPriority(PRIORITY_MAX) // 音を出す .setSound(defaultSoundUri) val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // 通知エリアに複数表示させるためランダムのIDを設定 val uuid = UUID.randomUUID().hashCode() notificationManager.notify(uuid, notificationBuilder.build()) // Android 8(Oreo)以上はチャンネルを指定 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { notificationBuilder.setChannelId(resources.getString(R.string.channel_id)) } } //Android 8(Oreo)以上はチャンネルを設定しないと通知エリアに表示されないためchannelidを設定 private fun addChannelId() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // ヘッドアップ通知を出す場合はチャンネルの重要度も最大にする val channel = NotificationChannel(resources.getString(R.string.channel_id),resources.getString(R.string.channel_name),NotificationManager.IMPORTANCE_HIGH) // ロック画面での表示レベル channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC // チャンネル登録 manager.createNotificationChannel(channel) } } } |
トークンが新しく生成された時以外で取得するにはonCreateなどで以下のように取得できます。
1 2 3 4 5 6 7 8 | // push通知のトークン取得 val pushToken = FirebaseInstanceId.getInstance().instanceId pushToken.addOnSuccessListener { instanceId -> val token = instanceId.token Log.d(TAG,"push token:$token") // サーバにトークンを送信する処理など } |
manifestファイルの設定
上で実装したクラスをmanifestファイルへ登録します。
1 2 3 4 5 6 7 | <service android:name=".SampleListenerService" android:permission="android.permission.INTERNET"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> |
最後に
これでFirebaseコンソールやPostmanなどで上で生成されたトークンを使えばpush通知が届くと思います。
Android8以上だとチャンネルを登録しないといけない点に注意ですね。
【参考サイト】
コメントを残す