PUSH通知を実装するのにgoogle先生のFCMを使用します、FCMがなんたるかなどの説明は省きますが、実装にあたってハマった点がいくつかあるのでその辺りを交えて説明します
FCMを使ってのPUSH通知
FCM側の設定
最初にgoogleのFirebaseコンソールでFCMの設定を行います、googleアカウントが必要なので持ってない方は作成しておいてください
例としてpush_noticeという名前をつけます、ロケーションはデフォルトの「us_central」を選択しました
プロジェクトの画面です、Sparkプランは無料のプランで、push通知はSparkプランでOKです。Android向けのPUSH通知を実装しますので、中央付近のAndroidのアイコンを選択します
config.xml
の冒頭、以下のwidget id="io.ionic.starter"
の箇所を修正して、上記のAndroidパッケージ名と一致させてください
<?xml version='1.0' encoding='utf-8'?> <widget id="io.ionic.starter" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> <name>push_notice</name> <description>An awesome Ionic/Cordova app.</description> <author email="hi@ionicframework" href="http://ionicframework.com/">Ionic Framework Team</author> ~~~
続いて設定ファイルのダウンロード、google-services.json
をダウンロードします
ダウンロードしたgoogle-services.json
はローカルのionicプロジェクト直下に配置してください
そして、platform配下の適切な場所に配置される必要がありますので、プラットフォームの追加、ビルド時にコピーされるように、config.xml
に定義を追記してください。今回はandroid向けなので、platformがandroidの定義の中に追加します
<platform name="android"> <allow-intent href="market:*" /> <icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" /> <icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png" /> <icon density="hdpi" src="resources/android/icon/drawable-hdpi-icon.png" /> <icon density="xhdpi" src="resources/android/icon/drawable-xhdpi-icon.png" /> <icon density="xxhdpi" src="resources/android/icon/drawable-xxhdpi-icon.png" /> <icon density="xxxhdpi" src="resources/android/icon/drawable-xxxhdpi-icon.png" /> <splash density="land-ldpi" src="resources/android/splash/drawable-land-ldpi-screen.png" /> <splash density="land-mdpi" src="resources/android/splash/drawable-land-mdpi-screen.png" /> <splash density="land-hdpi" src="resources/android/splash/drawable-land-hdpi-screen.png" /> <splash density="land-xhdpi" src="resources/android/splash/drawable-land-xhdpi-screen.png" /> <splash density="land-xxhdpi" src="resources/android/splash/drawable-land-xxhdpi-screen.png" /> <splash density="land-xxxhdpi" src="resources/android/splash/drawable-land-xxxhdpi-screen.png" /> <splash density="port-ldpi" src="resources/android/splash/drawable-port-ldpi-screen.png" /> <splash density="port-mdpi" src="resources/android/splash/drawable-port-mdpi-screen.png" /> <splash density="port-hdpi" src="resources/android/splash/drawable-port-hdpi-screen.png" /> <splash density="port-xhdpi" src="resources/android/splash/drawable-port-xhdpi-screen.png" /> <splash density="port-xxhdpi" src="resources/android/splash/drawable-port-xxhdpi-screen.png" /> <splash density="port-xxxhdpi" src="resources/android/splash/drawable-port-xxxhdpi-screen.png" /> <resource-file src="google-services.json" target="app/google-services.json" /> </platform>
上記の定義は、ionicプロジェクト直下のgoogle-services.json
を、対象のplatform(今回はandroid)のapp配下にコピーしますよ、という定義。
具体的には以下の場所にコピーされていればOKです。
どうしてもコピーされない!という場合は、直接上記のディレクトリに手動でコピーしてしまうのも手かもしれません、わりとここハマったので・・・
また、もう一点、死ぬほどハマった箇所がありますが、わたしの場合この後ビルドしたタイミングで以下のエラーが出て全く先に進めませんでした・・・
BUILD FAILED in 1m 20s cmd: Command failed with exit code 1 Error output: FAILURE: Build failed with an exception. * What went wrong: A problem occurred configuring project ':app'. > Cannot add task ':app:processDebugGoogleServices' as a task with that name already exists.
色々とググって出てきた修正を試していたのですが、うまくいかず。。。
っで、さっきのFirebaseの設定を進めると以下の画面が出てくるのですが、
ここのclasspath 'com.google.gms:google-services:4.0.1'
の追記が必要でした。
色んなサイトでplatforms\android\app\build.gradle
のgradleレベルを修正するだのなんだの、他にも様々な解決策があったのですが、わたしは結局以下のファイルを修正してうまくいきました(順序が前後して申し訳ないのですが、後述のプロジェクトの作成、fcmのプラグインのインストールなどを行った後に修正してください)
buildscript { repositories { jcenter() mavenLocal() } dependencies { classpath 'com.android.tools.build:gradle:2.3.+' classpath 'com.google.gms:google-services:4.0.1' } }
ここ、他のサイトではバージョンの指定が3.0.0
だったりしたので、この記事も古くなると恐らく使えなくなる点に注意です!
実装部分!
では、続いて実装の部分をやっていきましょう
まずはプロジェクトの作成、androidのplatformを追加します
C:\work\program\cordova\test\ionic>ionic start push_notice
C:\work\program\cordova\test\ionic\push_notice>ionic cordova platform add android
続いてFCMのプラグインを追加します
C:\work\program\cordova\test\ionic\push_notice>ionic cordova plugin add cordova-plugin-fcm-with-dependecy-updated > cordova plugin add cordova-plugin-fcm-with-dependecy-updated --save Installing "cordova-plugin-fcm-with-dependecy-updated" for android Android Studio project detected Subproject Path: CordovaLib Subproject Path: app Adding cordova-plugin-fcm-with-dependecy-updated to package.json Saved plugin info for "cordova-plugin-fcm-with-dependecy-updated" to config.xml C:\work\program\cordova\test\ionic\push_notice>npm install --save @ionic-native/fcm@beta npm WARN @ionic/angular-toolkit@1.0.0 requires a peer of @angular-devkit/architect@0.9.0-beta.3 but none is installed. You must install peer dependencies yourself. npm WARN @ionic/angular-toolkit@1.0.0 requires a peer of @angular-devkit/build-angular@0.9.0-beta.3 but none is installed. You must install peer dependencies yourself. npm WARN @ionic/angular-toolkit@1.0.0 requires a peer of @angular-devkit/core@0.9.0-beta.3 but none is installed. You must install peer dependencies yourself. npm WARN @ionic/angular-toolkit@1.0.0 requires a peer of @angular-devkit/schematics@0.9.0-beta.3 but none is installed. You must install peer dependencies yourself. npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.4 (node_modules\fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.4: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"}) + @ionic-native/fcm@5.0.0-beta.21 added 1 package from 1 contributor and audited 49770 packages in 13.357s found 0 vulnerabilities
そしたら、src/app/app.module.ts
とsrc/app/home/home.page.ts
を修正します
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RouteReuseStrategy } from '@angular/router'; import { IonicModule, IonicRouteStrategy } from '@ionic/angular'; import { SplashScreen } from '@ionic-native/splash-screen/ngx'; import { StatusBar } from '@ionic-native/status-bar/ngx'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app-routing.module'; import { FCM } from '@ionic-native/fcm/ngx'; @NgModule({ declarations: [AppComponent], entryComponents: [], imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule], providers: [ StatusBar, SplashScreen, FCM, { provide: RouteReuseStrategy, useClass: IonicRouteStrategy } ], bootstrap: [AppComponent] }) export class AppModule {}
import { Component } from '@angular/core'; import { FCM } from '@ionic-native/fcm/ngx'; @Component({ selector: 'app-home', templateUrl: 'home.page.html', styleUrls: ['home.page.scss'], }) export class HomePage { constructor(private fcm: FCM) { fcm.subscribeToTopic('marketing'); fcm.getToken().then(token => console.log(token)); fcm.onNotification().subscribe(data => { if (data.wasTapped) { console.log('Received in background'); } else { console.log('Received in foreground'); } }); fcm.onTokenRefresh().subscribe(token => { console.log(token); }); fcm.unsubscribeFromTopic('marketing'); } }
今回は簡易的にfcm.getToken().then(token => console.log(token));
で、コンソールログに端末のトークンを表示するようにしています、後述のメッセージ送信の時に説明しますね
ここまで来たらビルドしましょう!
C:\work\program\cordova\test\ionic\push_notice>ionic cordova build android --prod
もし、ビルドが失敗してしまう場合、根本的な原因が他にあるかもしれませんが、GitHubのissuesやstackoverflowで、「platformの追加・削除でキレイにしてもっかいやってみろ」、みたいなのをわりと見かけたので試してみてもいいかもしれません。
C:\work\program\cordova\test\ionic\push_notice>ionic cordova platform rm android
C:\work\program\cordova\test\ionic\push_notice>ionic cordova platform add android
メッセージの送信
まずエミュレータ上でアプリを起動して、chrome://inspect
からデバッグします
一部モザイクで隠していますが、先ほどfcm.getToken().then(token => console.log(token));
でトークンを出力するようにしていました、コイツがメッセージ送信の際に端末を特定する情報になります
(*`・ω・)ゞ
他にはFCMコンソール上で確認できるサーバキーというものが必要です、↓の「サーバーキー」という箇所
これらの情報からFCMのAPIに対してPOSTリクエストを送信するとメッセージが届きます、わたしはPHPで簡易的なPOST送信するゴミプロを作成して試しました
//FCMのAPIのURL $url = 'https://fcm.googleapis.com/fcm/send'; $fcm_server_key = '各々のサーバーキー'; $token = '端末のトークン'; $headers = array( 'Authorization: key='.$fcm_server_key, 'Content-Type: application/json' ); $data = array( 'notification' => array( 'title' => 'タイトル', 'body' => 'てすと', 'sound' => 'default', 'subtitle' => 'サブタイトル' ), 'data' => array( 'data' => 'test_message' ), 'to' => $token ); $options = array( 'http' => array( 'method' => 'POST', 'header' => implode( "\r\n", $headers ), 'content' => json_encode($data) ) ); $stream = stream_context_create( $options ); $contents = file_get_contents( $url, FALSE, $stream ); echo '<p>送信結果</p>'; var_dump(json_decode($contents));
$data
の中に'notification'
というのを定義していますが、これがいわゆるスマホの通知領域に届く部分のデータです。具体的なjsonの定義についてはFCMの公式リファレンスをご確認ください
送信した結果、うまくいくとPHP側では以下を受け取ります
object(stdClass)#1 (5) { ["multicast_id"]=> int(XXXXXXXXXXXXXXXXXXxx) ["success"]=> int(1) ["failure"]=> int(0) ["canonical_ids"]=> int(0) ["results"]=> array(1) { [0]=> object(stdClass)#2 (1) { ["message_id"]=> string(35) "0:XXXXXXXXXXXXXXXXXXXXXXXXXXXX" } } }
んで、エミュレータの方を見てみると~
やった~、きた~~~。:.゚ヽ(´∀`。)ノ゚.:。 ゜
関連記事
ionic4 – ハイブリッドアプリ制作にチャレンジしてみる①
ionic4 – ハイブリッドアプリ制作にチャレンジしてみる②
ionic4 – ハイブリッドアプリ制作にチャレンジしてみる③ – ページ遷移
ionic4 – ハイブリッドアプリ制作にチャレンジしてみる④ – FCMによるPUSH通知