Ionic+ReactでNFCタグを読み取れるアプリを作る

## 必要な条件

このチュートリアルでは, アンドロイドアプリを作っていきます。同じ手順でiPhoneアプリも作れるはずですが、テストしてみたことはありません。　Ionicは、Angular、Vue、React、およびvanilla　Javascriptで使用できます。 でも、このチュートリアルでは、React/Typescriptと一緒にIonicを使います。 チュートリアルに沿っていくには、次の条件が必要になります：

- android studio
- VsCode　（他のIDEでも良い） 
- Node (npm)
- Reactの基礎知識
- Typescriptの基礎知識

## 準備

コマンドラインを使用してionicCLIをダウンロードします: `$ npm install -g @ionic/cli`

IDEでIonicアプリを入れたいフォルダを開きます。 IDEのターミナルで、`ionic start`を実行します。アプリ作成ウィザードを使用するかどうか表示されるので、`Y` (yes)を選びます。初めて使う方は、アカウントを作る必要があります。良ければ、簡単にGitHubを通じてログイン出来ます。

好きなアプリ名、アイコンと色を選んで、listとReactを選択して「Create App」をクリックします。

![Capture d’écran (140).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2080708/5a43432f-a78a-cc97-e37d-20f32c995b15.png)

ターミナルでアプリの構築が始まります。結構時間がかかる可能性があります。アプリの構築が完了したら、プロジェクトフォルダにcdします。`ionic serve`を実行することで、localhostでアプリを開くことができます。
![Capture d’écran (141).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2080708/ea9e5e76-7b6c-b687-7b4a-c9e2bb47ffae.png)
これで、アプリ作成ウィザードのタブを閉じることができます。

次はphonegap-nfcをインストールします。
`npm i phonegap-nfc`
`npm i -D @types/phonegap-nfc`

[phonegap-nfc](https://github.com/chariotsolutions/phonegap-nfc#nfcaddmimetypelistener)はNFCタグの読み取りを可能にするCordovaプラグインです。

最後に、`npm install @capacitor/android` を実行します(iosの場合は`npm install @capacitor/ios`)。

## レイアウト

### Ionicのテーマ

良ければ、アプリの色は`src/theme/variables.css`で、変更できます。

### Ionicのコンポーネント

Ionicはさまざまなコンポーネントを提供しています。すべてのIonicコンポーネントの詳細については、ドキュメント[ドキュメンテーション](https://ionicframework.com/docs/components)を確認してください。

### ユーティリティクラス

Ionicは多くのユーティリティクラスを提供しています。BootstrapまたはTailwindの使い方は以ています。ユーティリティの完全なリストは[ここ](https://ionicframework.com/docs/layout/css-utilities)にあります。

ユーティリティクラスのCSSは、次の方法でインポートする必要があります: `import "@ionic/react/CSS/<file name>"`. [このリンク](https://ionicframework.com/docs/layout/global-stylesheets) にインポートできるファイルのリストがあります。
インポートできるCSSスタイルシートのリストが見えます。


## コード

srcフォルダで　components、pagesとdataフォルダを削除します。

App.tsxのコードをすべてを削除し、以下のコードに置き換えます。

```App.tsx
import React, { useState, useEffect } from "react";
import {
  IonApp,
  IonButton,
  IonContent,
  IonHeader,
  IonTitle,
  IonToolbar,
  setupIonicReact,
} from "@ionic/react";

//Ionicコンポーネントが正しく機能するために必要なコアCSS
import "@ionic/react/css/core.css";

//Ionicで構築されたアプリの基本的なCSS
import "@ionic/react/css/normalize.css";
import "@ionic/react/css/structure.css";
import "@ionic/react/css/typography.css";

//ユーティリティ用のCSS
import "@ionic/react/css/padding.css";

// import "@ionic/react/css/float-elements.css";
// import "@ionic/react/css/text-alignment.css";
// import "@ionic/react/css/text-transformation.css";
// import "@ionic/react/css/flex-utils.css";
// import "@ionic/react/css/display.css";

// テーマ変数
import "./theme/variables.css";

//アプリの手順のタイプ
type TStep =
  | "initializing"
  | "noNfc"
  | "nfcNotEnabled"
  | "waitingForNfcEnabled"
  | "waitingForTag"
  | "tagRead";

setupIonicReact();

const App: React.FC = () => {
  const [step, setStep] = useState<TStep>("initializing");
  const [tagContent, setTagContent] = useState("");

  useEffect(() => {
    initializeNfc();
  }, []);

  const initializeNfc = () => {
    //nfcがundefinedの場合、NFCはこのデバイスで使用できません、
    //またはアプリはウェブブラウザで実行されています
    if (typeof nfc !== "undefined") {
      // event listenerを登録
      nfc.addTagDiscoveredListener(
        onNfc, // イベントリスナーのコールバック関数
        () => {
          setStep("waitingForTag");
        }, // 成功→イベントを待っています
        () => setStep("nfcNotEnabled") // エラー → NFCは有効ではありません
      );
    } else {
      setStep("noNfc");
    }
  };

  const onGoToSettingsClick = () => {
    if (typeof nfc !== "undefined") {
      // ユーザーのNFC設定を開くようにデバイスに要求します
      nfc.showSettings(
        () => setStep("waitingForNfcEnabled"),
        () => alert("NFC設定を開こうとしたときにエラーが発生しました。")
      );
    }
  };

  const onNfc = (e: PhoneGapNfc.TagEvent) => {
    const array: Array<number> = e.tag.id;
    const stringTag: string = array.toString();

    setTagContent(stringTag);
    setStep("tagRead");
  };

  const resetTagReader = () => {
    setTagContent("");
    setStep("initializing");
    initializeNfc();
    console.log("resetting");
  };

  return (
    <IonApp>
      <IonHeader>
        <IonToolbar color="primary">
          <IonTitle>Ionic-NFC</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent>
        <div className="ion-padding ion-margin">
          <div className="nfc">
            {step === "initializing" ? (
              <div>初期化中...</div>
            ) : step === "noNfc" ? (
              <div>
                使用しているデバイスにNFCが搭載されていないようです。または
                PhoneGap-NFCプラグインが正しく設定されていません。
              </div>
            ) : step === "nfcNotEnabled" ? (
              <div>
                <div>
                  デバイスでNFCが有効になっていません。下のボタンをクリックして
                  デバイスの設定を開き、NFCをオンにして下さい。
                </div>
                <IonButton onClick={onGoToSettingsClick} className="ion-margin">
                  Go to NFC Settings
                </IonButton>
              </div>
            ) : step === "waitingForNfcEnabled" ? (
              <div>
                <div>NFCを有効にしたら、下のボタンをクリックしてください。</div>
                <IonButton onClick={initializeNfc} className="ion-margin">
                  NFCリーダーを初期化する
                </IonButton>
              </div>
            ) : step === "waitingForTag" ? (
              <div>
                <div>NDEFが付いてるカードをスキャンしてください。</div>
              </div>
            ) : (
              //step === "tagRead"
              <div>
                <div>スキャンしました! 内容:</div>
                <div>{tagContent}</div>
                <IonButton onClick={resetTagReader} className="ion-margin">
                  別のタグをスキャンする
                </IonButton>
              </div>
            )}
          </div>
        </div>
      </IonContent>
    </IonApp>
  );
};

export default App;
npx
```

## Androidアプリ化

Ionicには、Capacitorと呼ばれるツールが付属しており、コードをモバイルアプリケーションに簡単に変換できます。Androidアプリを作成するには、単に`npm run build`　、`npx cap add android`を実行します。
iosなら、`npx cap add ios`を実行します。
 
`android`というフォルダはプロジェクトのルートで現れます。そのフォルダをAndroid Studioで開きます。iosの場合には`ios`というフォルダをXcodeで開きます。　このチュートリアルの残りの部分では、Androidのみに集中していきます。

ソースコードを変更する時に、Androidプロジェクトを更新するために、ターミナルで次のコードをを実行する必要があります：

`npm run build`
`npx cap sync`

そうしたら、Android Studioで変更を適用してアクティビティを再開することが必要です。

## スマホでアプリ実行

### 開発者モード
スマホをパスコンに繋げるために、開発者モードを設定する必要があります。機種で異なるので、Googleで調べたほうがいいです。

Galaxy, Pixel, Xperia, AQUOSを持っている方は [この記事](https://appllio.com/android-development-mode-settings)を読んでください。

開発者モードの設定が終わったら、デベロッパーオプションで、USBダウンロードをオンにします。

### スマホを繋げる
USBケーブルで、スマホをパスコンに繋げます。スマホで、幾つかの選択肢が表示されたら`ファイル転送`をクリックします。

Android　Studioで、ドロップダウンメニューからスマホを選択します。スマホがメニューに表示されない場合は以下の点を確認してください：

- ケーブルは機能していますか？ちゃんと接続されていますか？
- `デベロッパーオプション`で`USBダウンロード`をオンにしましたか？

スマホを選択してからとなりの▶をクリックします。　スマホでは、ダウンロードを受け入れるように求められます。アプリが自動的に開かなければ,手動でアプリを開きます。

### アプリを使用する

Suicaや他のICカードまたはWaonカードを用意します。 カードをスマホの下（カメラの下）に置くと、カード番号がスマホ画面に表示されます。

## デバッギング

エラーが発生すれば、デバッグする方法が二つあります：

- logcat
- chrome devtols
#### logcat

AndroidStudioウィンドウの下部にあるオプションの中にlogcatがあります。

#### chrome devtools
`console.log`が使えるので、とても便利です。ケーブルで繋がっているスマホで、アプリを開きます。パソコンのchromeブラウザーで`chrome://inspect`を開いて、「inspect」をクリックします。
アプリが閉じるたびに切断されますので、その時にウィンドウを閉じて、もう一度「inspect」をクリックする必要があります。

## 役立リソース

[このプロジェクトのGithubレポジトリー](https://github.com/Code-Kat/Ionic-React-NFC)
[Ionic + React - Tutorial for Beginners 2020 (英語）](https://www.youtube.com/watch?v=_03VKmdrxV8&t=4971s)
[Ionic ドキュメンテーション　（日本語）](https://ionicframework.com/docs/ja)