はじめに

NativeScript + Firebase でプッシュ通知を行う方法。

TL;DR

目次

  1. はじめに
  2. TL;DR
  3. 環境・条件
  4. 詳細
    1. セットアップ
      1. Firebase プロジェクトの作成など
      2. プラグインのインストール
      3. 共通設定
      4. iOS
      5. Android
    2. その他, Tips
      1. 常にフォアグラウンドで通知(iOS Only)
      2. topic 購読/解除
    3. iOS でインタラクティブ通知
  5. まとめ
  6. 参考文献

環境・条件

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
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.3
BuildVersion: 19D76

$ node -v
v12.7.0

$ npm -v
6.10.3

$ tns --version
6.4.0

$ grep -C1 version package.json
"tns-ios": {
"version": "6.4.1"
},
"tns-android": {
"version": "6.4.1"
}

$ tns plugin
Dependencies:
┌──────────────────────────────┬─────────┐
│ Plugin │ Version │
│ @nativescript/theme │ ^2.2.1 │
│ @vue/devtools │ ^5.0.6 │
│ nativescript-plugin-firebase │ ^10.4.0 │
│ nativescript-socketio │ ^3.2.1 │
│ nativescript-toasty │ ^1.3.0 │
│ nativescript-vue │ ^2.4.0 │
│ nativescript-vue-devtools │ ^1.2.0 │
│ tns-core-modules │ ^6.0.0 │
│ vue-router │ ^3.1.5 │
└──────────────────────────────┴─────────┘
Dev Dependencies:
┌────────────────────────────────────┬─────────┐
│ Plugin │ Version │
│ @babel/core │ ^7.0.0 │
│ @babel/preset-env │ ^7.0.0 │
│ babel-loader │ ^8.0.2 │
│ nativescript-dev-webpack │ ^1.0.0 │
│ nativescript-vue-template-compiler │ ^2.0.0 │
│ nativescript-worker-loader │ ~0.9.0 │
│ node-sass │ ^4.9.2 │
│ vue-loader │ ^15.4.0 │
└────────────────────────────────────┴─────────┘
  • iPhone 11 Pro: iOS 13.3
  • Android HUAWEI nova lite 2: Android 9 (ビルド 9.1.0.160)

詳細

リポジトリ: 17number/nativescript-vue-tutorial

参考コミット(時系列順):

セットアップ

Firebase プロジェクトの作成など

参考: 条件は多少異なるが Vue + Cordova + Firebase でプッシュ通知 に手順をまとめている。

Identifier/Profile 作成(iOS 事前準備)

Identifier/Profile を作成して、キーチェーンへの登録などを実施する

iOS: Identifier/Profile 作成 を参照

Firebase プロジェクト作成、アプリ追加

プロジェクト作成とアプリ追加を行う

Firebase の設定 を参照

GoogleService-Info.plist(iOS), google-services.json(Android) をダウンロードできれば OK

ダウンロードしたファイルは app/App_Resources/iOS/, app/App_Resources/Android/ に配置。
※該当ディレクトリが無い場合は、プラットフォームを追加するなり、アプリを実行するなりすれば作成されると思われる。

1
2
3
# cp なり mv なりドラッグアンドドロップで配置
$ cp GoogleService-Info.plist app/App_Resources/iOS/
$ cp google-services.json app/App_Resources/Android/
APNs 証明書の登録(iOS)

.p12 ファイルを作成してアップロードする

APNs 証明書の登録 を参照

プラグインのインストール

tns plugin add nativescript-plugin-firebase を実行。色々と聞かれるので Firebase Cloud Messaging, In-App Messaging を有効化。
※各環境に合わせて適宜設定。

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
$ tns plugin add nativescript-plugin-firebase
...
prompt: Are you using iOS (y/n): (y) y
prompt: Are you using Android (y/n): (y) y
prompt: Do you want to enable Firebase Analytics? (y/n): (y)
prompt: Are you using Firestore? (y/n): (n)
prompt: Are you using Realtime DB? (y/n): (n)
prompt: Are you using Firebase Authentication (pretty likely if you use Firestore or Realtime DB)? (y/n): (y) n
prompt: Are you using Firebase RemoteConfig? (y/n): (n)
prompt: Are you using Performance Monitoring? (y/n): (n)
prompt: Are you using this plugin as a Push Notification client for an external (NOT Firebase Cloud Messaging) Push service? (y/n): (n)
prompt: Are you using Firebase Cloud Messaging? (y/n): (n) y # ***
prompt: Are you using In-App Messaging? (y/n): (n) y # ***
prompt: Are you using Firebase Crashlytics? (y/n): (n)
prompt: Are you using Firebase Storage? (y/n): (n)
prompt: Are you using Firebase Cloud Functions? (y/n): (n)
prompt: Are you using Firebase Facebook Authentication? (y/n): (n)
prompt: Are you using Firebase Google Authentication? (y/n): (n)
prompt: Are you using AdMob? (y/n): (n)
prompt: Are you using Firebase Dynamic Links? (y/n): (n)
prompt: Are you using ML Kit? (y/n): (n)
Successfully created iOS (Pod) file.
Install google-service.json after-prepare copy hook.
Install google-service.json before-checkForChanges copy hook.
Successfully created Android (include.gradle) file.
Install google-service.json after-prepare copy hook.
Install google-service.json before-checkForChanges copy hook.
Firebase post install completed. To re-run this script, navigate to the root directory of `nativescript-plugin-firebase` in your `node_modules` folder and run: `npm run config`.
prompt: Do you want to save the selected configuration. Reinstalling the dependency will reuse the setup from: firebase.nativescript.json. CI will be easier. (y/n): (y) n
...

共通設定

package.json 変更

アプリ作成時に Identifier を指定していない場合、com.example.nativescript.application になっていると思うので、前の手順で作成した Identifier に変更しておく。

package.json

1
2
3
4
5
6
7
8
9
 {
...
"nativescript": {
- "id": "com.example.nativescript.application",
+ "id": "id.of.your.app",
...
},
...
}
Token の受信処理 追加

app/main.js を編集し、token, message 関連の処理を追加。
※ひとまず tokenmessage をログ出力するだけにしているが、実際には適切な処理が必要。

1
2
3
4
5
6
7
8
9
10
11
12
13
...
import firebase from 'nativescript-plugin-firebase';

// プッシュ通知用トークンの更新
firebase.init({
onPushTokenReceivedCallback: token => console.log({token}),
onMessageReceivedCallback: message => console.log({message}),
})
.then(
() => console.log("firebase.init success"),
(error) => console.error(`firebase.init error: ${error}`)
);
...

iOS

iOS - Enabling Firebase Cloud Messaging (FCM)

pod repo update

pod repo update を実行
参考: iOS (Cocoapods)

1
$ pod repo update
Xcode の設定変更
1
$ open platforms/ios/<YourApp>.xcworkspace

.xcworkspace が無い場合は、tns run ios --bundle を実行すれば作成されるはず

Team, Bundle Identifier 変更

Push 通知有効化

設定ファイルのコピー

Push 通知用の設定ファイルが platforms/ios/<YourApp>/<YourApp>.entitlements or platforms/ios/<YourApp>/Resources/<YourApp>.entitlements に作成されているはずなので、app/App_Resources/iOS/ にコピー。

1
$ cp platforms/ios/<YourApp>/<YourApp>.entitlements app/App_Resources/iOS/

※開発用の場合は <string>development</string>、リリース用は <string>production</string> に設定

バックグラウンド通知の有効化

app/App_Resources/iOS/Info.plist を編集

1
2
3
4
5
6
7
8
9
 ...
<dict>
...
+ <key>UIBackgroundModes</key>
+ <array>
+ <string>remote-notification</string>
+ </array>
</dict>
...
動作確認(iOS)

ここまでできたら実機接続して tns run ios --bundle で確認。Firebase などのインストールが実行されるのでしばらく待つ。

1
2
3
4
5
6
7
8
9
10
$ tns run ios --bundle
...
Downloading dependencies
Installing Firebase (6.16.0)
Installing FirebaseAnalytics (6.2.2)
...
Integrating client project
Pod installation complete! There are 7 dependencies from the Podfile and 22 total pods installed.
Project successfully prepared (ios)
...

問題なければアプリケーションが起動して「通知許可のダイアログ」が表示される。コンソール上に token が表示されているので値をコピー。

1
2
3
...
CONSOLE LOG file:///app/bundle.js:663:14: { token: 'YourToken' }
...

Firebase コンソール からテストメッセージを送信して、iOS デバイスで受信できれば OK。

参考: プッシュ通知の受信確認

Android

app.gradle 編集

app/App_Resources/Android/app.gradle を編集

Google Play Services Version - EddyVerbruggen/nativescript-plugin-firebase に書かれているように project.ext の設定を追加。

1
2
3
4
5
6
7
8
9
 android {
defaultConfig {
...
+ project.ext {
+ googlePlayServicesVersion = "+"
+ }
}
...
}

メソッド数の上限に引っ掛かることがある(引っ掛かった)ので multiDexEnabled true を追加。
参考1: 64K を超えるメソッドを使用するアプリ向けに multidex を有効化する | Android デベロッパー
参考2: java - Android gives error “Cannot fit requested classes in a single dex file” - Stack Overflow
参考3: [Android]Android 64k問題を回避するための設定方法(Cannot fit requested classes in a single dex file / Too many field references) - みんなのプログラミング by Telulu LLC

1
2
3
4
5
6
7
8
9
10
 android {
defaultConfig {
...
project.ext {
googlePlayServicesVersion = "+"
}
+ multiDexEnabled true
}
...
}

ちなみに multiDexEnabled true を追加しないとビルド時に以下のエラーとなり、実行できなかった。

1
2
3
4
5
6
7
8
9
10
11
$ tns debug android --bundle
...
D8: Cannot fit requested classes in a single dex file (# methods: 104413 > 65536)
com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives:
The number of method references in a .dex file cannot exceed 64K.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html
at com.android.builder.dexing.D8DexArchiveMerger.getExceptionToRethrow(D8DexArchiveMerger.java:131)
...

Execution failed for task ':app:mergeDexDebug'.
Error: null, Cannot fit requested classes in a single dex file (# methods: 104413 > 65536)
動作確認(Android)

iOS と同様に実機接続して tns run android --bundle で確認。

1
2
$ tns run android --bundle
...

問題なければアプリケーションが起動、コンソール上に token が表示されているので値をコピー。

1
2
3
...
JS: { token: 'YourToken' }
...

あとは同じように Firebase コンソール からテストメッセージを送信して、Android デバイスで受信できれば OK。

なお、フォアグラウンドにしていると表示されない(はず)ので、バックグラウンドに切り替えてからメッセージを送った方が良い。
場合によっては通知ポップアップが表示されないかもなので、通知センターを開いておくほうがわかりやすい。(「通知ポップアップが表示されない」の原因までは追っていない)

その他, Tips

常にフォアグラウンドで通知(iOS Only)

firebase.init 時に showNotificationsWhenInForeground: true を設定すると、常にフォアグラウンドで通知される
参考: Always show notifications when the application is in foreground

1
2
3
4
firebase.init({
// ..
showNotificationsWhenInForeground: true,
});

ドキュメントには明記されていないが、コメント によると showNotificationsWhenInForeground: true は iOS 限定のもののようなので注意。

that’s an iOS-only property according to that documentation.
https://github.com/EddyVerbruggen/nativescript-plugin-firebase/issues/1136#issuecomment-460989406 より

Android で正しくシステム通知を表示させるには、送信メッセージのフォーマットを正しく指定すると良い(らしい)。
参考: https://github.com/EddyVerbruggen/nativescript-plugin-firebase/issues/1136#issuecomment-462447162

たぶん、Cordova で試したときの内容と同じ話。
参考: フォアグラウンドでのプッシュ通知受信

topic 購読/解除

参考: Send messages to Topics

1
2
3
4
5
6
7
// 購読
firebase.subscribeToTopic("news")
.then(() => console.log("Subscribed to topic"));

// 解除
firebase.unsubscribeFromTopic("news")
.then(() => console.log("Unsubscribed from topic"));

iOS でインタラクティブ通知

以下画像のようなことも可能

Interactive notifications (iOS only for now)

まとめ

参考文献

関連記事