Monaca + Vue.js + Firebase で匿名認証

スマホアプリ開発でiOS、Androidの両方を行ってみて思うのが、やっぱり2つ開発はシンドイと思います。
で、考えるのはハイブリッド開発でしょうか?
Web、Xamarin、React nativeなどいくつか選択肢がありますが、まずはMonacaというHTML5ベースのプラットフォームを試します。

今回は試しにFirebaseと連携し匿名認証を行います。
ユーザーをこちらから特定する必要はないですが、ユーザーの属性情報だけ欲しいというような使い方です。
試して思ったのですが、FirebaseではSNSアカウント、メールアドレスなどで認証するのも簡単そうです。

Monacaの開発環境はクラウド上ではなくローカルで行いました。
MonacaでVue.jsのテンプレートから作成しています。
また、Firebaseで匿名認証を許可する設定まで完了してる前提でプログラムのみ紹介。

src/public/index.html.ejs

まずはFirebaseの設定です。最初 www/index.html に書いたのですが、何かのタイミングでファイルが戻ってしまう?現象があったので、index.html.ejs に書きました。

<body>
  <div id="app"></div>
  <script src="https://www.gstatic.com/firebasejs/5.5.5/firebase.js"></script>
  <script>
    // Initialize Firebase
    var config = {
      apiKey: "{Firebaseから}",
      authDomain: "{Firebaseから}",
      databaseURL: "{Firebaseから}",
      projectId: "{Firebaseから}",
      storageBucket: "{Firebaseから}",
      messagingSenderId: "{Firebaseから}"
    };
    firebase.initializeApp(config);
  </script>
</body>

ここの設定は Firebase console の “ウェブアプリに Firebase を追加” から取得できます。

src/Home.vue

Monacaのテンプレートに入っているHome.vueを変更しています。
イメージは起動時に匿名認証を行っているか判定し、行っていなければダイアログでユーザー属性を入力させ、Firebaseで匿名認証させます。
認証時の属性情報は Firebase の Cloud Firestore に保存します。
あとで気づいたのですが Cloud Firestore は現在ベータ版で、Webで”Firebase database”で検索すると Realtime Database の情報も出てくるので混乱しました。

<template id="main">
  <v-ons-page>
    <div style="display: table; height: 100%; width: 100%;">
      <div style="display: table-cell;text-align: center;vertical-align: middle;">
        <p>
          Hi!
        </p>
        <p>
          <v-ons-button modifier="quiet" style="background-color: transparent;" @click="signOut">
            登録解除
          </v-ons-button>
        </p>
      </div>
    </div>

    <v-ons-modal style="background-color: #FFFFFF;" :visible="showSignInModal">
      <div style="text-align: center; color: #333333;">
        <p>
          あなたのことを教えてください。
        </p>
        <p>
          <v-ons-select class="signInSelect" v-model="gender">
            <option disabled="disabled" value="">性別</option>
            <option v-for="(item, index) in genders" :key="index" :value="item.value">
              {{ item.text }}
            </option>
          </v-ons-select>
        </p>
        <p>
          <v-ons-select class="signInSelect" v-model="generation">
            <option disabled="disabled" value="">年齢</option>
            <option v-for="(item, index) in generations" :key="index" :value="item.value">
              {{ item.text }}
            </option>
          </v-ons-select>
        </p>
        <v-ons-button modifier="outline" class="signInBtn" @click="signIn">次へ</v-ons-button>
      </div>
    </v-ons-modal>

    <v-ons-modal :visible="showLoading">
      <p style="text-align: center">
        Loading <v-ons-icon icon="fa-spinner" spin></v-ons-icon>
      </p>
    </v-ons-modal>
  </v-ons-page>
</template>

<script>
export default {
  data() {
    return {
      showLoading: false,
      showSignInModal: false,
      gender: "",
      genders: [
        { text: "男性", value: "MALE" },
        { text: "女性", value: "FEMALE" },
        { text: "その他", value: "OTHER" }
      ],
      generation: "",
      generations: [
        { text: "10歳未満", value: "_10" },
        { text: "10-19歳", value: "10_19" },
        { text: "20-29歳", value: "20_29" },
        { text: "30-39歳", value: "30_39" },
        { text: "40-49歳", value: "40_49" },
        { text: "50-59歳", value: "50_59" },
        { text: "60-69歳", value: "60_69" },
        { text: "70-79歳", value: "70_79" },
        { text: "80歳以上", value: "80_" }
      ]
    };
  },
  methods: {
    signIn(event) {
      this.showLoading = true;
      // 匿名ユーザサインイン
      firebase
        .auth()
        .signInAnonymously()
        .catch(function(error) {
          alert(error.message);
        });
    },
    signOut(event) {
      firebase.auth().signOut();
    }
  created() {
    var self = this;
    firebase.auth().onAuthStateChanged(function(user) {
      if (user) {
        const firestore = firebase.firestore();
        firestore.settings({ timestampsInSnapshots: true });
        firestore
          .collection("users")
          .doc(user.uid)
          .set({
            gender: self.gender,
            generation: self.generation
          })
          .then(function() {
            self.showLoading = false;
            self.showSignInModal = false;
          })
          .catch(function(error) {
            console.error("Error writing document: ", error);
            alert("登録に失敗しました");
          });
      } else {
        self.showSignInModal = true;
      }
    });
  }
};
</script>

こんな感じでユーザー情報がFirebase の Authentication と Database(Cloud Firestore) に登録されます。

user.uid をキーにアプリデータをFirebaseのDatabaseに保存すれば、アンケートみたいなものは簡単に作れそうです。
もちろん要件によってはiOS、Androidを別々に開発すべきですが、要件を満たせるならハイブリッドで開発するのは十分にアリだと思います。
ただ、バックグラウンド処理やBLE周りとかどうなんでしょう?

「Monaca + Vue.js + Firebase で匿名認証」への2件のフィードバック

  1. ありがたく読ませていただきました。
    一つ気になる点がありました。
    SyntaxErrorになると思うのですが正しくは以下でしょうか?

    export default {
    data() {
    return {
    showLoading: false,
    showSignInModal: false,
    gender: “”,
    genders: [
    { text: “男性”, value: “MALE” },
    { text: “女性”, value: “FEMALE” },
    { text: “その他”, value: “OTHER” }
    ],
    generation: “”,
    generations: [
    { text: “10歳未満”, value: “_10” },
    { text: “10-19歳”, value: “10_19” },
    { text: “20-29歳”, value: “20_29” },
    { text: “30-39歳”, value: “30_39” },
    { text: “40-49歳”, value: “40_49” },
    { text: “50-59歳”, value: “50_59” },
    { text: “60-69歳”, value: “60_69” },
    { text: “70-79歳”, value: “70_79” },
    { text: “80歳以上”, value: “80_” }
    ]
    };
    },
    methods: {
    signIn(event) {
    this.showLoading = true;
    // 匿名ユーザサインイン
    firebase
    .auth()
    .signInAnonymously()
    .catch(function(error) {
    alert(error.message);
    });
    },
    signOut(event) {
    firebase.auth().signOut();
    },
    created() {
    var self = this;
    firebase.auth().onAuthStateChanged(function(user) {
    if (user) {
    const firestore = firebase.firestore();
    firestore.settings({ timestampsInSnapshots: true });
    firestore
    .collection(“users”)
    .doc(user.uid)
    .set({
    gender: self.gender,
    generation: self.generation
    })
    .then(function() {
    self.showLoading = false;
    self.showSignInModal = false;
    })
    .catch(function(error) {
    console.error(“Error writing document: “, error);
    alert(“登録に失敗しました”);
    });
    } else {
    self.showSignInModal = true;
    }
    });
    }
    }
    }

    あと一つお聞きしたいことがあるのですが、monacaとfirebaseの連携が出来ずに困っております、
    monacaデバッガーでは、firebaseの連携はできませんか?

    1. ご指摘ありがとうございます。SyntaxError になっていましたか、スミマセン。
      この記事だとmonacaはあくまで見た目のViewとしてだけ利用しているので、`monacaとfirebaseの連携` というよりは単純にFirebaseと連携できていないのかもしれませんね。
      FirebaseのAuthenticationの設定あたりで、匿名認証が有効になっているか?承認済みのドメインに追加されているか?といった辺りが想像されますが、だいぶ前の記事なのでご容赦ください。

master へ返信する コメントをキャンセル

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

CAPTCHA