ionic4 – ハイブリッドアプリ制作にチャレンジしてみる④ – FCMによるPUSH通知(Android)

PUSH通知を実装するのにgoogle先生のFCMを使用します、FCMがなんたるかなどの説明は省きますが、実装にあたってハマった点がいくつかあるのでその辺りを交えて説明します

 

FCMを使ってのPUSH通知

 

FCM側の設定

最初にgoogleのFirebaseコンソールでFCMの設定を行います、googleアカウントが必要なので持ってない方は作成しておいてください

Googleアカウントにログインして、コンソールへ移動
001_firebase_console

 
プロジェクトを追加
002_firebase_console

 
例としてpush_noticeという名前をつけます、ロケーションはデフォルトの「us_central」を選択しました
003_add_project

 
待ちます
004_provisining

 
出来ました
005_finish

 
プロジェクトの画面です、Sparkプランは無料のプランで、push通知はSparkプランでOKです。Android向けのPUSH通知を実装しますので、中央付近のAndroidのアイコンを選択します
006_push_notice_project

 
Androidパッケージ名のところにアプリ名称を入れます
007_add_firebase_for_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をダウンロードします
008_add_firebase_for_android

 
ダウンロードしたgoogle-services.jsonはローカルのionicプロジェクト直下に配置してください
009_google_services_json

 
そして、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です。
010_google_services_json

どうしてもコピーされない!という場合は、直接上記のディレクトリに手動でコピーしてしまうのも手かもしれません、わりとここハマったので・・・

 
また、もう一点、死ぬほどハマった箇所がありますが、わたしの場合この後ビルドしたタイミングで以下のエラーが出て全く先に進めませんでした・・・

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'の追記が必要でした。

011_add_firebase_sdk

 
色んなサイトで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.tssrc/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からデバッグします

012_chrome_inspect

 
一部モザイクで隠していますが、先ほどfcm.getToken().then(token => console.log(token));でトークンを出力するようにしていました、コイツがメッセージ送信の際に端末を特定する情報になります
(*`・ω・)ゞ

 
他にはFCMコンソール上で確認できるサーバキーというものが必要です、↓の「サーバーキー」という箇所
013_server_key

 
これらの情報から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"
    }
  }
}

 
んで、エミュレータの方を見てみると~

014_result

 
やった~、きた~~~。:.゚ヽ(´∀`。)ノ゚.:。 ゜

 

関連記事

ionic4 – ハイブリッドアプリ制作にチャレンジしてみる①
ionic4 – ハイブリッドアプリ制作にチャレンジしてみる②
ionic4 – ハイブリッドアプリ制作にチャレンジしてみる③ – ページ遷移
ionic4 – ハイブリッドアプリ制作にチャレンジしてみる④ – FCMによるPUSH通知

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です