【2019年5月】{N} + ng + Firebase : 準備編

# NativeScript + Angular で Firebase をバックエンドにしてみたい。

先月の記事 [【2019年4月版】NativeScript+Angularで感じた新時代](https://qiita.com/koinori/items/aa2a3e124331117704db) で [**{N} + ng = ❤**](https://www.nativescript.org/nativescript-is-how-you-build-native-mobile-apps-with-angular) に入門いたしましたが、バックエンドに Firebase 使えないのか？！ということで調べてみました。

あっさりと以下のように Firebase プラグインを発見いたしました。これだけでいけるのか？！

- [NativeScript Firebase plugin](https://github.com/EddyVerbruggen/nativescript-plugin-firebase)

また以下の記事で NativeScript での Firebase 利用についてさっくりとご紹介いただいておりました。

- [NativeScriptでPUSH通知を受信する（Firebase編）](https://qiita.com/terushu/items/3b0d1eaaf3f681af3e7e)

これはいろいろと夢が膨らみますね！

さっそく手元で実際の構築手順を再現してみました。

**いろいろ手間取りましたので本日は "Firebaseに接続する" ところまでの「準備編」といたします。**

## 対象環境

OS : macOS High Sierra
Android SDK : platform 27 revision 3
実機 : Android 7.1.1
NativeScript-Angular : 7.2.0

前回とは違い、今回は macOS での構築です。

## 環境の構築手順

## NativeScript のインストール

{N} のインストールには以下の公式サイトの構築手順に従ってセットアップを進めて行けばOKです。

- [https://docs.nativescript.org/angular/start/quick-setup](https://docs.nativescript.org/angular/start/quick-setup)
- [https://docs.nativescript.org/angular/start/ns-setup-os-x](https://docs.nativescript.org/angular/start/ns-setup-os-x)

`yarn` の対応はイマイチのようなので諦めて `npm` を使用します。

```console
$ npm install -g nativescript
```

ここでは紹介しませんが以下のバージョンの java や Android SDK のインストールをお願いします。

- JDK 8
- Android SDK
- Android Support Repository
- Google Repository
- Android SDK Build-tools 28.0.3 or a later stable official release
- Android Studio

注意点は `JDK 8` と `Android SDK Build-tools 28.0.3` ですね。バージョンは確認しておきましょう。

またインストール中に iOS 用に xcode のインストールをしつこく勧めてきますが、Android だけの場合は `Skip Step and Configure Manually` で飛ばしてOKです。

念のため、以下のコマンドで Android SDK などが正しくインストールされているか確認しましょう。

```console
$ tns doctor
```

## プロジェクトの作成

以下のコマンドでプロジェクトを作成します。

```console
$ tns create HelloWorld --template tns-template-blank-ng
```
生成される package.json の `id` に `org.nativescript.HelloWorld` とあると思います。

これがこの**アプリケーションのID**となります。

## firebase のプロジェクト準備

firebase でのプロジェクト作成と、"Android"　用の `gooogle-services.json` の取得、app.gradle の修正をFirebaseの案内手順通りに行います。
上記の**アプリケーションのID**を貼り付けてください。

1. `gooogle-services.json` を `HelloWorld/App_Resources/Android/google-services.json` に保存します。
2. app.gradle を以下のように修正します。

```gradle:app.gradle
dependencies {
  implementation 'com.google.firebase:firebase-core:16.0.1'
}

android {
  defaultConfig {
    minSdkVersion 17
    generatedDensities = []
  }
  aaptOptions {
    additionalParameters "--no-version-vectors"
  }
  project.ext {
    googlePlayServicesVersion = "+"
  }
}

apply plugin: 'com.google.gms.google-services'
```

具体的には `dependencies`の追加、`googlePlayServicesVersion = "+"`の追加、"apply plugin:" の追加を行なっています。

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

以下の Readme のセットアップ手順でだいたいOKです。

- [https://github.com/EddyVerbruggen/nativescript-plugin-firebase](https://github.com/EddyVerbruggen/nativescript-plugin-firebase)

肝は Firebase の `google-services.json` の準備が整ってから、firebase プラグインをインストールする、という点でしょう。
以下のコマンドで firebase プラグインをインストールします。

```console
$ tns plugin add nativescript-plugin-firebase
```
ここで firebase の様々な機能について `有効にするか？` と聞いてきます。
お好みに応じて `y` としておきましょう。

以上でプロジェクトの準備は完了です。

# 実装手順 

今回は firebase への接続を確認するだけなので、app.component.ts を以下のように修正するだけです。

```typescript:app.component.ts

import { Component, OnInit } from "@angular/core";

const firebase = require("nativescript-plugin-firebase");

@Component({
    moduleId: module.id,
    selector: "ns-app",
    templateUrl: "app.component.html"
})
export class AppComponent {
  // using async-await just for show
  ngOnInit() {
    try {
      firebase.init({
        persist: false
      });
      console.log(">>>>> Firebase initialized");
    } catch (err) {
      console.log(">>>>> Firebase init error: " + err);
    }
  }
}
```
これでアプリケーションの起動時に、コンソールのログで `>>>>> Firebase initialized` と出力されればまず、第一関門突破です。

## いつものように preview ・・・？

`AppComponent` の生成がうまくいくか確かめたいので、例によってプレビューアプリで確認してみます。

```console
$ tns preview
```
ところが起動時にエラーが発生して {N} Preview アプリにログが表示されてしまいます。。。

ログメッセージでググって見た結果、firebase plugin は {N} preview のアプリには含まれていないので、 `tns preview` コマンドでは動かないとのこと。。。

- https://github.com/EddyVerbruggen/nativescript-plugin-firebase/issues/1033#issuecomment-467889282

> Like I said: it's not part of the Preview app, so you can't use that.

・・・はい。~~先に言ってね〜~~

# Android 実機でのデバッグ

というわけで実機で動かす必要ありです。以下のコマンドのヘルプを参照しまして・・・

https://docs.nativescript.org/tooling/docs-cli/project/testing/debug-android

USB で実機を接続後、

```
$ tns device android

Connected devices & emulators
Searching for devices...
┌───┬─────────────┬──────────┬───────────────────┬────────┬───────────┐
│ # │ Device Name │ Platform │ Device Identifier │ Type   │ Status    │
│ 1 │ XXXXXXXX    │ Android  │ J5AXHM00S6047MX   │ Device │ Connected │
└───┴─────────────┴──────────┴───────────────────┴────────┴───────────┘

```

で認識されているか確認。`Device Identifier` をコピーして以下のコマンドで貼り付けます。

```
$ tns debug android --device J5AXHM00S6047MX
```
しばらくビルドが進んでおりましたが・・・以下のようにエラーが発生しました。

```
* What went wrong:
Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'.
> 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
```
・・・はい、ということで `app.gradle` を修正します。

```gradle:app.gradle
android {
  defaultConfig {
    minSdkVersion 17
    generatedDensities = []
    multiDexEnabled true
  }
  aaptOptions {
    additionalParameters "--no-version-vectors"
  }
  project.ext {
    googlePlayServicesVersion = "+"
  }
}
```
`multiDexEnabled true` を追記いたしました。

再度、気を取り直して・・・

```console
$ tns debug android --device J5AXHM00S6047MX
...
Project successfully built.
Installing on device J5AXHM00S6047MK...
Successfully installed on device with identifier 'J5AXHM00S6047MX'.
Restarting application on device J5AXHM00S6047MX...
JS: >>>>> Firebase initialized
JS: Angular is running in the development mode. Call enableProdMode() to enable the production mode.
device: J5AXHM00S6047MX debug port: 40000

To start debugging, open the following URL in Chrome:
chrome-devtools://devtools/bundled/inspector.html?experiments=true&ws=localhost:40000

Successfully synced application org.nativescript.HelloWorld on device J5AXHM00S6047MX.
```

動いたー！！！
いろいろありましたがついに `>>>>> Firebase initialized` のコメントを拝むことができました!!
これで `firebase` オブジェクトが使用可能になった模様です！

初回のビルドは例によって非常に時間かかります。その間、気長にお待ちください。
~~(私は実機の接続が必須と知ってから Android SDK 28 をインストールし始めたのでさらに時間がかかってしまいました。。。)~~

引き続き {N} + Firebase の開発で firebase の各種機能についていろいろ試してみたいと思います。