ラベル Firebase の投稿を表示しています。 すべての投稿を表示
ラベル Firebase の投稿を表示しています。 すべての投稿を表示

2021年12月7日火曜日

Fireabase CLI を使って Realtime Database のデータをエクスポートする

Fireabase CLI を使って Realtime Database のデータをエクスポートする

概要

毎回ブラウザで Firebase にログインしてエクスポートするのは面倒なので CLI を使います

環境

  • macOS 11.6.1
  • firebase cli 9.23.0

コマンド

  • firebase --project project_id database:get / > export.json

project_id の部分は firebase projects:list で表示される Project ID を入力しましょう

上記だとルートパスからすべてのデータをエクスポートしています
パスを指定すれば一部のデータだけエクスポートすることもできます

2021年12月2日木曜日

(Mac) Firebase CLI をインストールする

(Mac) Firebase CLI をインストールする

概要

macOS に firebase CLI をインストールしてセットアップする方法を紹介します

環境

  • macOS 11.6.1
  • firebase cli 9.23.0

インストール

オムニバスインストールできるようなスクリプトが準備されているのでそれを使います
管理者権限のパスワードが求められるので入力します

-- Checking for existing firebase-tools on PATH...
-- Checking your machine type...
-- Downloading binary from https://firebase.tools/bin/macos/latest
######################################################################## 100.0%
-- Setting permissions on binary...
-- Checking your PATH variable...
-- firebase-tools@9.23.0 is now installed
-- All Done!

動作確認

ログインできるか確認しましょう

  • firebase login

ブラウザが開くのでログインしましょう
firebase cli に oauth で権限を与えれば OK です

  • firebase projects:list

でプロジェクトの一覧が表示されれば OK です

参考サイト

2021年7月6日火曜日

Firebase の File Storage の使い方

Firebase の File Storage の使い方

概要

Firebase の File Storage を使ってみました ファイルのダウンロードをする際に少し気をつけることがありました インストール方法や初期化の部分は省略しています

環境

  • macOS 11.4
  • Xcode 12.5.1
  • Firebase/Storage 7.11.0

ローカルへのファイルのダウンロード

ポイントはファイルを保存できるパスが決まっているという点です 自分のアプリ配下の Documents にしか保存できないので注意しましょう

自分の Documents 配下を参照するためのプロパティがちゃんと提供されているのでそれを使うのが無難です

import Firebase

let storage = Storage.storage()
let storageRef = storage.reference()
let name = "test.txt"
let testfileRef = storageRef.child(name)
let fileManager = FileManager.default
let articlePath = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
let localURL = articlePath.appendingPathComponent(name)

_ = testfileRef.write(toFile: localURL) { url, error in
    if let error = error {
        // firebase からファイルの取得失敗
        print(error)
    } else {
        // ファイルのダウンロードに成功
	print("success")
    }
}

メタ情報の参照

例えばファイルの md5 ハッシュを取得するには以下のようにします 取得可能なメタデータの一覧はこちらにあります

fndbfileRef.getMetadata { metadata, error in
    if let error = error {
        // firebase のメタデータの取得に失敗
        print(error)
    } else {
      	// メタデータの取得に成功
        print(metadata?.md5Hash)
    }
}

参考サイト

2020年6月2日火曜日

Firebase のプッシュ通知に APNs 認証キーを使用する方法

概要

Firebase でプッシュ通知を送信するのに証明書ではなく認証キーを使って送信することができるようになりました
認証キーを使うことで証明書にあった期限切れなどが発生しないため更新作業が不要になります

環境

  • Firebase (2020/06/01 時点)
  • Apple Developer Portal (2020/06/01 時点)

プッシュ通知用の Key の作成

  • https://developer.apple.com/account/resources/certificates/list にアクセス
  • 「Keys」に移動
  • 「Create a key」を選択
  • 「Key Name」を入力 -> 「Apple Push Notifications service (APNs)」を選択 -> 「Continue」を選択 -> 「Registre」を選択
  • 「Download」を選択し p8 ファイルがダウンロードできたことを確認する

p8 ファイルは一度だけダウンロードできるのでしっかり保存しておくこと

Firebase にアップロード

  • Firebase のコンソールにログイン
  • 左上の歯車から「プロジェクトを設定」を選択
  • 「クラウドメッセージング」タブを選択
  • キーをアップロードするアプリを選択し「APNs 認証キー」から p8 ファイルをアップロード

Tips

KeyID と TeamID は Devloper Portal で確認できます
https://developer.apple.com/account/resources/authkeys/list

Firebase でアプリに TeamID を事前に設定しておく必要があります
「プロジェクトを設定」->「全般」-> (アプリ選択を選択) -> 「チームID」を編集すれば OK です

最後に

APNs 認証キーを作成し Firebase に登録する方法を紹介しました
UI などはいろいろと変更になるのでボタンの名前などが変わっている場合があるのでご注意ください

これとは別に AppID やプロビジョニングプロファイルなどは Developer Portal で作成する必要があるので作成しておきましょう

参考サイト

2019年6月28日金曜日

Firebase のデータを Redis に格納する Ruby スクリプト

概要

メモがてら残しておきます
Firebase の認証はレガシーな Database Secret を使っています

環境

  • macOS 10.14.5
  • Ruby 2.6.2p47

準備

  • bundle init
  • vim Gemfile
gem "firebase"
gem "redis"
  • bundle install --path vendor

アプリ

  • vim app.rb
require './lib/my_fb.rb'
require './lib/my_redis.rb'

p MyRedis.store(MyFB.fetch_all)

firebase の処理

  • vim lib/my_fb.rb
require 'firebase'

module MyFB
  BASE_URL = 'https://product_id.firebaseio.com/'
  SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

  def fetch_all
    client = Firebase::Client.new(BASE_URL, SECRET)
    ret = {}
    ret.store('category1', client.get('db1/category1').body)
    ret.store('category2', client.get('db1/category2').body)
    ret
  end

  module_function :fetch_all
end

Redis の処理

  • vim lib/my_redis.rb
require 'redis'
require 'json'

module MyRedis

  def store(ret)
    client = Redis.new
    sum = 0
    ret.each do |key, ary|
      ary.each_with_index do |p, i|
        client.set("#{key}_#{i}", p.to_json)
      end
      client.set("#{key}", ary.length)
      sum += ary.length
    end
    sum
  end

  module_function :store
end

Redis には category1_0 のような key で登録します
後からインデックスで検索、ループ処理しやすいように各カテゴリごとのデータのサイズを category1 という key に登録しています

実行

  • bundle exec ruby app.rb

動作確認

redis-cli get category1_0 で JSON の値が取得できれば OK
また redis-cli get category1 でコンテンツの数が取得できれば OK

最後に

サブカテゴリみたいに更に階層が深い場合にはループを増やせば OK です
Redis も localhost を前提にしているので外部なのであれば URL を指定してください

2018年3月28日水曜日

firebase-admin を使って nodejs から Firebase を操作するサンプル

概要

firebase-ruby だとリアルタイムデータベースを扱えないので nodejs の firebase-admin を使ってみました
今回紹介するサンプルはリアルタイムデータベースからデータを取得して一定条件だった場合に特定のペイロードにプッシュ通知を送信するサンプルです

環境

  • macOS 10.13.2
  • firebase-admin 5.11.0
  • nodejs 8.7.0

サンプルコード

事前に Firebase Admin SDK の管理画面から新しい秘密鍵を生成して JSON ファイルをダウンロードしておいてください

var admin = require('firebase-admin');

var serviceAccount = require('./project-firebase-adminsdk-xxxxx-xxxxxxxxxx.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: 'https://project-name.firebaseio.com/'
});

var db = admin.database();
var ref = db.ref("path/to/ref");
ref.on("child_added", function(snapshot) {
  var val = snapshot.val();
  console.log(val.id);
  // ある条件に合う場合は
  if (val.id.startsWith("push_")) {
    // プッシュ通知を送信する
    console.log("send push");
    var topic = "topic";
    var payload = {
      notification: {
        title: "Hello",
        body: "This message sent from nodejs"
      }
    };
    admin.messaging().sendToTopic(topic, payload)
      .then(function(response) {
        console.log("Successfully sent message:", response);
      })
      .catch(function(error) {
        console.log("Error sending message:", error);
      });
  }
},function (errorObject) {
  console.log("The read failed: " + errorObject.code);
});

ref.on を使うことでデータが登録される度に function(snapshot) がコールされます
イベントにはいくつが種類があり今回は child_added というイベントを指定しています
このイベントは子要素が追加されたときだけ関数内の処理が実行されるイベントです

プッシュ通知は admin.messaging().sendToTopic で行います
今回は特定のトピックに対して送信しています
あとのその結果を表示しているだけです

参考サイト

2018年3月27日火曜日

Firebase でトピックを Subscribe してプッシュ通知を送信してみる

概要

過去に Firebase で iOS にプッシュ通知を送信してみました
そのときは特にトピックを指定しなかったので全端末にプッシュ通知が送信されてしまいます
トピックは特定の端末群に対してプッシュ通知を送信するための機能です
今回はトピックを使ってプッシュ通知を送信してみました

あと事前に過去の記事を元に最低限のプッシュ通知の設定と実装は済ませておいてください (プッシュ用の証明書の登録, p12 ファイルの登録, プッシュ通知用の設定)

環境

  • macOS 10.13.2
  • Xcode 9.2 (9C40b)
  • FirebaseMessaging 2.1.1

トピックを Subscribe する

以下のメソッドをコールすることでトピックを Subscribe することができます

import FirebaseMessaging
Messaging.messaging().subscribe(toTopic: "topic-random_match")

こんな感じです、簡単ですね

Unsubscribe する

トピックを購読したくなくなった場合は Unsubscribe メソッドをコールする必要があります

Messaging.messaging().unsubscribe(fromTopic: "topic-random_match")

これも同じようにコールするだけなので簡単ですね

テスト送信

ではテスト送信してみましょう
Firebase の管理画面で Notifications から送信してみましょう
ポイントとしては当然ですが送信時にトピックを指定してください
firebase_topic_push1.png

これでトピックを subscribe している端末にだけ送信できると思います
端末がフォアグランドで動作しているとプッシュ通知が来ないのでバックグラウンドに移動しましょう

ON/OFF テクニック

subscribe/unsubscribe メソッドは当然あるのですが isSubscribe メソッド的なものはまだないようです
調べてみると Github で issue は上がっているようです
https://github.com/firebase/firebase-ios-sdk/issues/225

なので ON/OFF する場合は自分で実装する必要があります
自分の場合ですが単純にローカルに ON/OFF のデータを持つようにしました
RealmSwift を使って Bool の値を保存しているだけです

あとはその値を元に subscribe したり unsubscribe するだけです
subscribe 中に subscribe をコールしても特に問題はないようです (重複して受け取ることは自分の端末では起こりませんでした)

Tips

Cannot parse topic name topic/random_match. Will not subscribe. subscribe したときに出る場合があります
どうやらスラッシュを入れることができないのでハイフンなどに変えてみましょう

最後に

Firebase のプッシュ通知でトピック機能を使ってみました
簡単に使うのは使えますが少し機能が欠けているので、足りない機能は自分で補完する必要があります

今回は管理画面から送信しましたが Ruby などからも送信できるので、その場合もトピックを指定すれば便利な使い方ができるかなと思います

参考サイト

2018年3月8日木曜日

Firebase Swift で observe が複数回コールされてしまう場合に確認すること

概要

Firebase からデータを取得する場合 observe or observeSingleEvent を使うと思います
observeSingleEvent の場合は特に問題ないのですがリアルタイムでデータを取得したい場合には observe を使います
その場合に何故か 1 度しかデータを更新していないのに observe が複数回コールされる現象に遭遇したので対策を紹介します

環境

  • macOS 10.13.2
  • Xcode 9.2 (9C40b)
  • Firebase 4.8.2

確認する点

いくつか紹介します

単純にデータを複数回更新していないか

Swift からデータを更新する際には setValue or updateChildValues を使うと思います
単純にこれらが複数回コールされていないか確認しましょう
例えば touchDown などのイベントが発生したら上記メソッドを呼ぶようなケースだとすると連打などの対策をしていないと同じデータが複数回更新される可能性があります

Firebase の場合データが同じであっても更新イベントがあれば observe してしまいます

observe を removeObserver していない

自分はこっちでハマリました
observe の場合 removeObserver をしないといくら View が変わってもデータの監視が続いてしまうようです
これは SpriteKit でも同様で SKScene が変わった時に removeObserver していないと複数回コールされてしまうことがあります

removeObserver は例えば以下のように使います

var bmref = DatabaseReference()
var handler: UInt = 0

bmref = rootRef.child("path/to/data")
handler = bmref.observe(.value, with: { (snapshot) in
    bmref.removeObserver(withHandle: handler)
    move(to: scene)
})

move(to :scene) は適当にこちらで定義したシーンを移動するためのメソッドです
要するにシーンの移動直前に removeObserver を呼ぶようにしましょう
removeObserver の引数には observe を識別するためのハンドラが必要です
これは observe を登録した際の戻り値として取得することができます
ハンドラはインスタンス変数などにして別のメソッドからも参照できるようにしておきましょう

これで observe を削除することができます

observe が複数コールされる場合の影響

自分の場合は SpriteKit 上で使っていたのですが observe が複数回コールされることで fps が低下するという現象が発生しました

具体的に言うと SKAction.move などで動いているノードがある状態で observe が複数回コールされるとノードが一瞬 (0.5 - 1 秒ほど) 停止する状態になります
これが必要最低限のみコールされるようになることで fps が落ちることなくノードが動き続けてくれます

最後に

Swift + Firebase で observe が複数回コールされてしまう場合の対策を紹介しました
observe が削除されていない場合には削除するように修正してみてください

それでも重い、fps が落ちるという場合には単純に Firebase に対してアクセスしすぎていないか確認してみてください (1 秒間に 100 回データを更新するような処理をしていないかなど)

そういう場合にはずっと observe しないで定期的に observeSingleEvent するような仕組みに変更するようにしてみてください

2018年2月14日水曜日

Firebase でリアルタイムデータベースを使ってみた

概要

過去にデータの保存と取得を試しました
リアルタイムなやり取りはやっていなかったので試してみました
また今回は SpriteKit を使っています

環境

  • macOS 10.13.2
  • Xcode 9.2 (9C40b)
  • Firebase 4.8.2

Firebase にアプリを追加

コンソール画面から追加しましょう
追加したら
GoogleService-Info.plist をプロジェクトに追加します

ライブラリインストール

  • pod init
  • vim Podfile
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'test-proj' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for test-proj
  pod 'Firebase/Core'
  pod 'Firebase/Database'
  pod 'Firebase/AdMob'

  target 'test-projTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'test-projUITests' do
    inherit! :search_paths
    # Pods for testing
  end

end
  • pod install

初期化

  • AppDelegate.swift
import UIKit
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        FirebaseApp.configure()
        return true
    }
}

didFinishLaunchingWithOptions 内で FirebaseApp.configure() を実行しているだけです

リアルタイムにデータを取得する

  • GameScene.swift
import SpriteKit
import FirebaseDatabase

class GameScene: BaseScene {

    let rootRef = Database.database().reference()

    override func didMove(to view: SKView) {
        let bmref = rootRef.child("test-proj")
        bmref.observe(.value, with: { (snapshot) in
            let value = snapshot.value as? NSDictionary
            let room = value!["rooms"] as? NSDictionary
            print(room!["id"] as! Int)
        })
    }
}

observe を登録することで、そのコールバック内でデータが更新されたときの挙動を処理することができます
今回は階層的なデータを登録してそのデータを表示するだけです

動作確認

動作確認の前にシミュレータでアプリを起動しておきます
今回はコンソールにデバッグ表示するだけです
.sks ファイルには Hello World のラベルが定義されていますが気にしません

認証をオフにする

とりあえず今回はテストなので前許可にしちゃいます
コンソールから設定しましょう

Database -> ルール

firebase_realtime1.png

ちなみに認証をオンにして使いたい場合は Anonymous 認証ですが、こちらを御覧ください

テストデータを登録する

コンソールからデータを登録してみます

Database -> データ

firebase_realtime2.png

すると登録した瞬間コンソールに登録した数字が表示されると思います
firebase_realtime3.png

最後に

Firebase でリアルタイムデータベースを使って挙動を確認してみました
今回の場合構造的なデータを登録したので構造が間違っているとキャストに失敗して Exception が発生します

データの登録に関しては setValue をコールする感じです

今回はシミュレータ+管理コンソールでやりましたが次回は実機+シミュレータでやってみたいと思います 

参考サイト

2017年7月8日土曜日

Ruby で Firebase のプッシュ通知を送信する方法

概要

前回 Firebase を使って単一のデバイスにプッシュ通知を送信してみました
そのときはコンソールを使いましたが今回は Ruby から送信してみたいと思います
所謂、自動送信などを実現することができます

環境

  • mac OS X 10.12.5
  • Xcode 8.3.3 (8E3004b)
  • Ruby 2.2.3p173

ライブラリインストール

  • bundle init
  • vim Gemfile
gem "fcm"
  • bundle install

サーバキーの取得

Firebase のコンソールから取得できます
ログイン後

プロジェクトの設定 -> クラウドメッセージング -> サーバキー

で取得できます

firebase_push_with_ruby1.png

コード

  • vim send_push.rb
# coding: utf-8
require 'fcm'

fcm = FCM.new("先ほど取得したサーバキーはここに入力します")

token = "eIWudgln0C4:APA91bHA9sX7WNO6cBVAzV_DLZ89Ap54SSg6uNPOtWn8VLGdJlxutyu458yUR4yrz7ILNcNCaK5sAWhIyqq8W16XXPLfnDrenjmf_OBpLm5dJGCeZXrZ8hn5eJM2d8AYw8uQG8Gkj5E0"
opts = {
  "notification" => {
    "body" => "新着記事があります!"
  }
}
ret = fcm.send_with_notification_key(token, opts)
p ret

実行

  • bundle exec ruby send_push.rb

で成功すると以下のようなレスポンスが得られます

{:body=>"{\"multicast_id\":8431807027711221811,\"success\":1,\"failure\":0,\"canonical_ids\":0,\"results\":[{\"message_id\":\"0:1499328992939718%350c1818350c1818\"}]}", :headers=>{"content-type"=>["application/json; charset=UTF-8"], "date"=>["Thu, 06 Jul 2017 08:16:33 GMT"], "expires"=>["Thu, 06 Jul 2017 08:16:33 GMT"], "cache-control"=>["private, max-age=0"], "x-content-type-options"=>["nosniff"], "x-frame-options"=>["SAMEORIGIN"], "x-xss-protection"=>["1; mode=block"], "server"=>["GSE"], "alt-svc"=>["quic=\":443\"; ma=2592000; v=\"39,38,37,36,35\""], "accept-ranges"=>["none"], "vary"=>["Accept-Encoding"], "connection"=>["close"]}, :status_code=>200, :response=>"success"}

200 で返ってくれば OK です

ちょっと説明

今回の場合 notification というキーを使っています
これを使うことで通知が届くのですが、他に data というキーもありこれはカスタム用のペイロードを設定するためのキーなので、プッシュ通知は送信できるのですが、実際に通知バーに通知が出ません
所謂サイレントプッシュなどに使うためのキーになります
各種キーの詳細は参考サイトにある Firebase の公式ページを参考にすると良いと思います

また、API でプッシュ通知を送信した場合、なんとコンソール画面のプッシュ通知の一覧に表示されません
理由はわかりませんが現状はそういう仕様らしいので、履歴として管理したいのであれば何かしら自分で仕組みを作成する必要がありそうです

そしてもう一つ問題なのがコンソールではターゲットセグメントでアプリに対してプッシュ通知を送信できるのですが、API だとそれができません
なので、強制的に /all みたいなトピックを Subscribe するような実装をアプリ側で行い、その /all に対してプッシュ通知を送信することでアプリを使っている全ユーザに配信することができるようになります

最後に

Ruby を使って Firebase のプッシュ通知を送信してみました
1 つの端末に送信する方法を紹介しましたが、同じようにトピックにも送信することができると思います
指定するキーを間違えないようにしないとうまくプッシュ通知を受信することができないことがあるのでキーの内容については確認することをおすすめします

アプリ全体に送信することができなかったり、コンソールに結果が表示されないなど少し不可解な仕様はありますが、とりあえず今回の方法でプログラムからプッシュ通知を送信することはできると思います

参考サイト

2017年7月7日金曜日

Firebase で単一のデバイスにだけプッシュ通知を送信する方法

概要

前回 Firebase のプッシュ通知をとりあえず試しました
Firebase のプッシュ通知には送信対象としてユーザセグメント (アプリ)、トピック、単一の端末 (FCM トークン) の 3 種類があります
今回はその中の単一の端末に送信する方法を紹介します

環境

  • mac OS X 10.12.5
  • Xcode 8.3.3 (8E3004b)
  • iPhone5 (通知テスト用の実機)

AppDelegate にトークンを取得する処理を追加

didFinishLaunchingWithOptions を以下のように編集します

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Firebase の初期化
    FIRApp.configure()
    // プッシュ通知の許可を表示する
    if #available(iOS 10.0, *) {
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: {_, _ in })
        // For iOS 10 display notification (sent via APNS)
        UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
        // For iOS 10 data message (sent via FCM)
        FIRMessaging.messaging().remoteMessageDelegate = self as? FIRMessagingDelegate
    } else {
        let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
        application.registerUserNotificationSettings(settings)
    }
    application.registerForRemoteNotifications()
    // オブザーバを設定し端末トークンの更新監視をします
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(self.tokenRefreshNotification(_:)),
        name: NSNotification.Name.firInstanceIDTokenRefresh,
        object: nil)
    // すでにローカルにトークン情報がある場合はそれを表示する
    if let refreshedToken = FIRInstanceID.instanceID().token() {
        print("InstanceID token: \(refreshedToken)")
    }
    return true
}

ポイントは NotificationCenter.default.addObserver の部分でこれを登録することで端末トークンが更新されたときにトークンが表示されるようにします
もし、すでにトークンがローカルにある場合はそれを表示します

そして addObserver で追加している端末トークンが更新された際に呼ばれる関数「tokenRefreshNotification」を追加します

// トークンの更新があった場合にコールされます
func tokenRefreshNotification(_ notification: Notification) {
    if let refreshedToken = FIRInstanceID.instanceID().token() {
        print("Refresh InstanceID token: \(refreshedToken)")
    }
}

これで準備 OK です
当然ですが実機でなければトークンを取得できないので実機を接続してください

アプリを実機にインストールしてトークンを取得する

今回はコンソールログに出力しているだけなので、アプリを起動したらコンソールログを確認しましょう
今回であれば以下のように表示されれば OK です

Refresh InstanceID token: eIWudgln0C4:APA91bHA9sX7WNO6cBVAzV_DLZ89Ap54SSg6uNPOtWn8VLGdJlxutyu458yUR4yrz7ILNcNCaK5sAWhIyqq8W16XXPLfnDrenjmf_OBpLm5dJGCeZXrZ8hn5eJM2d8AYw8uQG8Gkj5E0

このトークンを使ってプッシュ通知を送信します

動作確認

今回は Firebase のコンソール画面からプッシュ通知を送信してみます
ログインして Notifications の画面に移動し新しいメッセージを作成します
そしてターゲットの部分で「単一の端末」を選択して先ほどのトークンを入力しましょう
firebase_single_push1.png

これで送信するとテストしていた実機にだけプッシュ通知が行くことを確認できると思います

通知が届かない場合は

まずアプリをインストールしたときのプッシュ通知の確認で許可するようにしましょう

あとはアプリがバックグランドにいる必要があります
フロントですでに動作している状態ではプッシュ通知は動作しません

今回は紹介しませんでしたが、p12 証明書を設定する必要もあるのでその辺りもしっかり Firebase に設定されているか確認してください
テスト用のプッシュ通知になるので development 用のプッシュ通知証明書から p12 ファイルを作成する必要もあります

最後に

Firebase で指定した 1 端末にだけプッシュ通知を送信する方法を紹介しました
Firebase の場合端末情報をデータベースに保存するのは自分でやる必要があるので、もし端末トークンを管理したい場合は登録する処理を書きましょう

おそらく登録しないのは登録しても誰のどの端末か全くわからないので、手元にある実機でコンソール出力して確実に端末がわかる状態で送信できれば問題ないのでそうしているんだと思います

今はなき Parse.com などは端末トークンをバックエンド側に保存する機能があったのでコンソール画面などでも確認できたのですが、Firebase の場合そういった機能はないのでコンソール画面でも端末トークンの一覧を確認することはデフォルトではできません

参考サイト

2017年6月30日金曜日

Firebase で Database を使う方法

概要

前回 アノニマス認証の方法を紹介しました
今回は認証後に Firebase のリアルタイム Database にアクセスしてみたいと思います
データベースのルールを変更することで認証しているかどうかでアクセスできるかできないかも検証してみます

環境

  • macOS X 10.12.5
  • Xcode 8.3.3 (8E3004b)
  • Firebase/Core/Auth/Database 4.0.2

データベースへのアクセスルール

とりあえず以下のように設定します

{
  "rules": {
    ".read": "auth != null",
    ".write": "auth != null"
  }
}

このルールは「どんなアカウントでもいいので認証済み」であれば read も write もできるルールになります

データベースに保存する

  • ViewController.swift
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase

class ViewController: UIViewController {

    var ref: DatabaseReference!

    override func viewDidLoad() {
        super.viewDidLoad()
        Auth.auth().signInAnonymously(completion: { (user, error) in
            if let e = error {
                print(e)
                print("login error")
                return
            }
            print(user?.displayName ?? "no displayName")
            print(user?.isAnonymous ?? false)
            self.ref = Database.database().reference()
            // データの保存
            self.ref.child("users").setValue(["username": user?.uid])
        })
    }
}

データベースを参照するための変数「ref」を定義しておきログイン後に接続します (Database.database().reference())
そして ref.child.setValue を使ってデータを保存します
認証に成功するとデータベースに write する権限があるため以下のようにデータが投入されます
firebase_anonymous3.png

権限を変更して挙動を確認する

次に write の権限を変更してみます

{
  "rules": {
    ".read": "auth != null",
    ".write": false
  }
}

false に変更しました
こうすることでデータベースに対してどんなユーザでもアクセスできなくなります
実際にアプリをビルドし直して試してみるとコンソールに

<Warning> [Firebase/Database][I-RDB038012] setValue: or removeValue: at /users failed: permission_denied

というデバッグ文が出力されているのがわかると思います

データを取得する

ついでに取得もやってみましょう
* ViewController.swift

// データの取得
self.ref.child("users").observeSingleEvent(of: .value, with: { (snapshot) in
    print(snapshot.value ?? "no value")
})

を保存の下に追記すれば OK です
今回は observeSingleEvent を使いました
リアルタイム Database にはイベントドリブンでデータを取得する方法もありデータが追加されたらイベントが発行され、その都度何か処理する方法もあります

その辺りの方法は参考サイトの URL を参考に試してみてください
やり方はほとんど同じようにできると思います

最後に

Firebase のリアルタイム Database を使ってみました
また今回は使いませんでしたが、イベントドリブンな取得もできるのでチャットアプリなどの開発が捗る機能かなと思います

参考サイト

2017年6月29日木曜日

Firebase で Anonymous 認証を使う方法

概要

Firebase のアノニマス認証を使ってみました
簡単な利用方法を紹介します

環境

  • macOS X 10.12.5
  • Xcode 8.3.3 (8E3004b)
  • Firebase/Core/Auth 4.0.2

Firebase 側の設定

デフォルトではアノニマス認証はオフになっていて使えません
Firebase のコンソールにログインして有効にする必要があります

Authentication -> ログイン方法 (タブ) -> 匿名

で有効にします
firebase_anonymous1.png

また、アプリの GoogleService-Info.plist をダウンロードしてプロジェクトにコピーしてください
firebase_anonymous2.png

ライブラリインストール

  • pod init
  • vim Podfile
target 'firebase-test' do
  use_frameworks!

  # Pods for firebase-test
  pod 'Firebase/Core'
  pod 'Firebase/Auth'
end
  • pod install

初期化

  • AppDelegate.swift
import UIKit
import CoreData
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        FirebaseApp.configure()
        return true
    }
    // 途中省略...
}

import して FirebaseApp.configure() を実行します

ログイン認証

本題です

  • ViewController.swift
import UIKit
import Firebase
import FirebaseAuth

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        Auth.auth().signInAnonymously(completion: { (user, error) in
            if let e = error {
                print(e)
                print("login error")
                return
            }
            print(user?.displayName ?? "no displayName")
            print(user?.isAnonymous ?? false)
        })
    }
}

signInAnonymously を呼ぶ感じです
completion のコールバックメソッドにログイン後のユーザ情報 or エラー情報が返ってきます

最後に

Firebase のアノニマス認証の方法を紹介しました
認証のあとにデータベースなどにアクセスするロジックを実装する感じです

Swift の Firebase のライブラリは現在バージョン 4 ですが、3 から上がった時に非互換な部分が多かったようでググって出たページが古いとクラスがなかったり関数がなかったりと動作しないケースが多かったです
公式のドキュメントですら古いケースがあったので Xcode の補完を使ったりコードを直接見ると良いかもしれません

参考サイト

2017年6月22日木曜日

firebase-ruby の get, push, set, update, delete の挙動を確認してみた

概要

前回 は firebase-ruby を使った GettingStarted 的な記事を紹介しました
今回はリアルタイムデータベースを操作できるその他のメソッドについて挙動を確認してみました

環境

  • CentOS 7.3.1611
  • ruby 2.3.3p222
  • firebase-ruby 0.2.6

使用するコード

  • bundle init
  • vim Gemfile
gem "firebase"
  • bundle install
  • vim test.rb
require 'firebase'

class FB
  BASE_URI = 'https://project-id.firebaseio.com/'
  SECRET_KEY = 'your-database-secret-key'

  def initialize
    @client = Firebase::Client.new(BASE_URI, SECRET_KEY)
  end

  def get(path, query)
    @client.get(path, query)
  end

  def push(path, hash)
    @client.push(path, hash)
  end

  def set(path, hash)
    @client.set(path, hash)
  end

  def update(path, hash)
    @client.update(path, hash)
  end

  def delete(path, query)
    @client.delete(path, query)
  end
end

f = FB.new

res = f.push('test', { :name => "hoge" })
id = res.body['name']
res = f.get("test/#{id}", {})
p res.body['name'] # => "hoge"

f.set('test1', { :name => "fuga" })
res = f.get('test1', {})
p res.body['name'] # => "fuga"

f.update("test/#{id}", { :name => "hogehoge" })
res = f.get("test/#{id}", {})
p res.body['name'] # => "hogehoge"
f.update('test1', { :name => "fugafuga" })
res = f.get('test1', {})
p res.body['name'] # => "fuga"

f.delete("test/#{id}", {})
f.delete('test1', {})
  • bundle exec ruby test.rb

BASE_URI と SECRET_KEY は自分のプロジェクトの値を設定してください

挙動説明

firebase-ruby にはデータを登録するためのメソッドが 2 つ用意されています
push と set があります

push の場合、基本的に毎回新規オブジェクトの追加となります
追加したオブジェクトに自動で ID を振ってくれるため、その ID でオブジェクトを識別します
ID は push したレスポンス情報に含まれています

方や set は指定したパスにそのままデータを登録します
なので 2 回 set しても内容は変わりません、オブジェクトも増えません
get でアクセスする場合のパスにも ID が含まれることはありません

get は path を指定してデータを取得します
path 配下にあるオブジェクトに対して絞り込みを行いたい場合はクエリを使います
https://firebase.google.com/docs/reference/android/com/google/firebase/database/Query
例えば上位 10 件のみを取得したい場合は limit を使います

あとは update と delete ですが、これも path で取得したオブジェクト配下の情報を削除したり更新したりします
update に関しては上書き更新なのでデータが新規で登録されるということはありません
delete に関しては物理削除なので、一度削除したオブジェクトは再度戻すことはできません

最後に

firebase-ruby が用意している関数の挙動を確認してみました
個人的には push ではなく set を使ってデータ登録したほうが毎回 ID を走査しなくて済むので簡単かなと思います

あとは get, update, delete を使って登録したデータを path を指定して操作する感じかなと思います

Firebase のデータベース機能はリアルタイムデータベースなので push や set で登録したときのアプリ側の挙動も確認したいと思っています
また Firebase には他にもストレージやホスティング機能、スクリプト機能があるのですが、firebase-ruby ではデータベース機能に対する制御しかできません
ストレージなどを使いたい場合は直接 Google Storege を操作する感じになるみたいです

参考サイト

2017年6月12日月曜日

Firebase で iOS にプッシュ通知を送信してみた

概要

プッシュ通知を Firebase に移行してみたので設定や流れをメモしておきます
ある程度端折っいる流れもあるのでその点はあしからず
基本は公式ドキュメントを見ることをおすすめします

環境

  • macOS 10.12.5
  • Xcode 8.3.2 (8E2002)
  • Firebase (2017/6/9 時点)
  • プッシュ対象端末 iPhone5 iOS 10.3.2

流れ

AppID にプッシュ通知用の証明書を登録する

作成するときは AppID の一覧から作成することをおすすめします
iOS Certificates にログインして

Identifiers -> App IDs -> 対象の AppID を選択 -> Edit

で編集画面に移動し「Push Notifications」の欄をチェックオンにします
そしてそこから「Create Certificate」でプッシュ通知用の証明書を作成します
作成には CSR が必要になるので事前に作成します
Development, Production 用の証明書の 2 つが作成できれば OK です
firebase_push1.png

作成したプッシュ通知用の証明書から p12 ファイルを書き出す

先ほどの画面から証明書を「Download」できるので Mac 上にダウンロードします
そして、ダブルクリックしてキーチェーンアクセスで開いて p12 ファイルを書き出しましょう
firebase_push3.png

パスワードはなしで書き出しました
後から気づいたのですが、Firebase は p12 ファイルのパスワードも設定できるのでパスワードはありでも大丈夫だと思います

p12 ファイルを Firebase に登録する

Firebase のコンソールにログインしましょう

プロジェクトの設定 -> クラウドメッセージング -> 対象のアプリを選択 -> APNs 証明書

を選択します
同じような項目で「APNs 認証キー」という項目がありますが、そっちじゃないので注意してください
firebase_push4.png

「開発用 APNs 証明書」「本番環境の APNs 証明書」という 2 つの欄があるので書き出した p12 ファイルをそれぞれアップロードしてください
ちゃんと Development 用の証明書から書き出した p12 ファイルは「開発用の APNs 証明書」Production 用の証明書から書き出し p12 ファイルは「本番環境の APNs 証明書」に設定しましょう
当然ですが、間違えるとプッシュ通知が送信されません

アプリ側修正

これで Firebase 側の設定は完了です
アプリ側の修正をしていきましょう

ライブラリのインストールは Cocoapods を使います

pod 'Firebase/Messaging'

プロジェクトのプッシュ通知を有効にします
プロジェクトを選択した状態で Capabilities を選択し「Push Notifications」を ON にします
firebase_push2.png

あとは AppDelete.swift を編集します
今回は Swift3 の文法を使っています
Swift2 だと若干コールするメソッドが違うので気をつけてください
全部紹介すると長いのでポイントを紹介します

import UserNotifications

を import しましょう

// Firebase の初期化
FIRApp.configure()
// プッシュ通知の許可を表示する
if #available(iOS 10.0, *) {
    let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
    UNUserNotificationCenter.current().requestAuthorization(
        options: authOptions,
        completionHandler: {_, _ in })
    // For iOS 10 display notification (sent via APNS)
    UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
    // For iOS 10 data message (sent via FCM)
    FIRMessaging.messaging().remoteMessageDelegate = self as? FIRMessagingDelegate
} else {
    let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
    application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()

didFinishLaunchingWithOptions に追加します
これでアプリの初回起動時にプッシュ通知を許可するかどうかのダイアログが出るようになり、許可を押した人にプッシュ通知できるようになります

// メッセージ受信時の処理
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
    print(userInfo)
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    print(userInfo)
    completionHandler(UIBackgroundFetchResult.newData)
}

メッセージを受信したときの処理です
メッセージをカスタマイズしていて何か特別な処理をしたいときはここにロジックを記載します

動作確認

これで OK なはずです
あとは Firebase の Notifications からメッセージを作成して送信すればメッセージが届くはずです

当然ですが実機でないと届きません
なので、Mac に iPhone を接続して Firebase 対応したアプリをビルドしてインストールしてください
アプリ起動時にプッシュ通知の許可拒否のダイアログが表示されるのでそこでも必ず許可を選択してください

最後に

Firebase を使って iOS にプッシュ通知を送信してみました
自分が一番ハマったのは証明書の部分で始め Production 用の証明書と p12 ファイルしか登録しないでやっていたら全然プッシュ通知が届かなく、Development 用の証明書も作成したら届くようになりました

あとはコードの部分ですが、今回のコードは公式のドキュメントに記載されていることとほぼ同様です
でも「firebase ios push」あたりでググると公式ドキュメントが一番最初に出てきません
引っかかった記事のサンプルコードを使っていたのですが、単純にプッシュ通知したいだけなのに setAPNSToken を使っていたりしてうまく動作しませんでした
単純にプッシュ通知を受け取りたいだけなら上記のコードだけで十分だと思います
それ以外にもアプリがアクティブになった場合のプッシュ通知の処理や、通知の開封状況などを解析するためのコードがありますが単純にプッシュ通知したい場合であれば不要です

あともう一点良くわからなかったのは Firebase ではプッシュ通知を送信するときに単一の端末にだけ送信する機能があります
そのときに「FCM 登録トークン」というものを使うのですが、これが Firebase 上のどこで確認できるかさっぱりわかりませんでした
コード上でデバッグする方法はドキュメントに載っていたのですが、コンソール上で確認する方法はわかりませんでした
たぶん、個別配信をするときは FCM 登録トークンを使わないで、トピックを使ってやれということだとは思います
FCM 登録トークンは開発者が知りたい時に直接コードにデバッグコードを埋め込んで取得しましょうというスタンスなんだと思います
それともどっかで確認できるのかもしれませんが、、

参考サイト

2016年11月18日金曜日

firebase-admin を使ってサーバからデータベースを操作してみた

概要

Firebase へのデータの保存と取得をサーバサイドからやってみました
今回は公式の nodejs のライブラリを使って操作してみました

環境

  • Mac OS 10.12.1
  • nodejs 5.9.1
  • firebase-admin 4.0.2

認証情報の取得

Firebase にアクセスするための admin ユーザの認証情報を取得します
認証情報は各プロジェクトごとに割り当てられています
まず Firebase のコンソール画面から「権限」を選択します
firebase_admin_download_auth1.png

すると Google の IAM 管理の画面に移動するので左メニューからサービスアカウントを選択します
一覧の中に「firebase-adminsdk」というユーザがいるので、一番右のメニューから「鍵を作成」を選択します
firebase_admin_download_auth2.png

鍵のフォーマットを選択する画面になるので JSON を選択して鍵を生成します
すると認証情報が記載された json ファイルがダウンロードできます
firebase_admin_download_auth3.png

この json ファイルを使って Firebase に認証します

ライブラリのインストール

では、nodejs を使ってプログラミングしていきます
まずは公式が公開しているライブラリをインストールします

  • npm install firebase-admin --save

で OK です

初期化

まずは Firebase にアクセスするために認証情報を使って初期化します

var admin = require("firebase-admin");
var serviceAccount = require("./your-project-admin.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://your-db-id.firebaseio.com/"
});

var database = admin.database();

ダウンロードした認証情報のファイルを require で読み込みます
あとは initializeApp 関数を呼び出してデータベースを初期化します

以降は database オブジェクトを操作することでデータの読み書きを行います

データの保存

先ほどの初期化した処理の下にデータを保存する処理を追記しましょう
teamA/users というパスの配下にユーザを追加するような処理になっています

var ref = database.ref("teamA");                                                                                                  
var usersRef = ref.child("users");
usersRef.set({
  hawk: {
    age: 1,
    sex: "male"
  },
  snow: {
    age: 1,
    sex: "famale"
  }
});

実行して Firebase のコンソールでデータを確認すると以下のように表示されると思います
firebase_admin_saved_data.png

データの取得

続けて保存したデータを取得してみたいと思います
snapshot という単位で保存したデータを取得します
初期化のあとに以下を記載してください

var ref = database.ref("teamA");                                                                                                  
ref.on("value", function(snapshot) {
  console.log(snapshot.val());
}, function (errorObject) {
  console.log("The read failed: " + errorObject.code);
});

データが取得できると実行したコンソール画面に以下のように表示されると思います

{ users: 
   { hawk: { age: 1, sex: 'male' },
     snow: { age: 1, sex: 'famale' } } }

ちなみに、node を実行している状態でコンソールからデータを追加するとそのデータもリアルタイムで node 側にデータが表示されると思います
firebase_admin_push_data.png

{ users: 
   { hawk: { age: 1, sex: 'male' },
     log: { age: 2, sex: 'male' },
     snow: { age: 1, sex: 'famale' } } }

最後に

nodejs から Firebase へのデータの保存と取得を行ってみました
データベースは Firebase だと「Realtime Database」という位置づけになるので、取得などの処理は少し癖のある感じになっています

Websocket や MQTT のように一度コネクションを張れば基本はそのコネクションを使いまわしてデータの取得をリアルタイムに行っている感じだと思います

一応クエリやフィルタの概念はあるので検索やソートできると思います
その辺りも後で検証してみたいなとは思っています
あとはサーバサイドからの更新や削除もやってみようかなと思います

参考サイト

2016年11月14日月曜日

Ruby で Firebase のデータベースにレガシーな方法でデータを保存してみた

概要

Ruby から Firebase のデータベースにデータを保存してしました
タイトルにある通りレガシーな方法を紹介します
レガシーというのは認証部分のことを指しており、今回紹介する方法は今後推奨されない方法、廃止される方法となる可能性が高いのでご注意ください 

環境

  • Mac OS X 10.10.5
  • Ruby 2.3.1p112
  • Gem 2.5.1
  • firebase 0.2.6

事前準備

Firebase へのプロジェクトの作成およびアプリケーションの作成は予め実施しておいてください
この記事内では過去に作成したアプリを使います

認証情報の取得

Ruby クライアントが使用する認証情報を取得します
この認証を使う方法がレガシーな方法になっています

作成したプロジェクトを開き

プロジェクトの設定 -> サービスアカウント -> データベースのシークレット -> シークレット -> 表示する

でシークレットキーを取得できるのでメモしておいてください

アクセスするとわかると思いますがここでも「データベースのシークレットは既に廃止されており、レガシーの Firebase トークン生成ツールを使用します。Firebase Admin SDK を使用してソースコードを更新してください。」と出て来ます
ruby_firebase_legacy_getting_secret.png

ベース URI の取得

各プロジェクトごとに割り当てられているデータベース用のベース URI を取得します
プロジェクトから左メニューの「データベース」を選択すると表示されるのでメモしておきます
ruby_firebase_legacy_getting_baseuri.png

データを保存するスクリプトの作成

取得した認証情報とベース URI を使用してスクリプトを作成します

  • bundle init
  • vim Gemfile
gem "firebase"
  • vim test.rb
require "firebase"

base_uri = 'https://your-project-id.firebaseio.com/test'
secret_key = 'your-secret-key'

firebase = Firebase::Client.new(base_uri, secret_key)

response = firebase.push("todos", { :name => 'Pick the milk', :priority => 1 })
puts response.success?
puts response.code
puts response.body
puts response.raw_body
  • bundle install
  • bundle exec ruby test.rb

で実行までできます
base_urisecret_key の部分は取得した情報を記載しましょう

動作確認

認証エラー等が出ないで 200 が返ってくればデータが保存されています
コンソールで Database を確認すると以下のように値が保存されているのがわかると思います
ruby_firebase_legacy_ret.png

最後に

Ruby で Firebase に値を保存してみました
取得する方法もあるのですが、クエリを使ってフィルタを掛けるのに苦戦しています、、、
こちらもわかったらポストしようかなと思います

あとは、認証方式も正式なやつを使った版を試してみようかなと思います

参考サイト

2016年10月25日火曜日

Xcode7 で Firebase/AdMob を導入する方法

概要

Admob は Google が提供するアプリに広告を入れられるサービスです
Google が Firebase をモバイルのプラットフォームとして統合したことで Admob も Firebase と連携できるようになりました
Admob 単体でも組み込むことができるのですが、Firebase とリンクさせて使うことで Firebase の Analytics 機能も使えるようになります
また、後々を考えてプラットフォームは Firebase に統合されるのを見据えて今回は Firebase 版の Admob を使ってみたいと思います

環境

  • Mac OS X 10.10.5
  • Xcode 7.2.1
  • Cocoapods 1.0.1
  • Google-Mobile-Ads-SDK 7.9.1
  • Firebase/AdMob 3.4.0
  • Firebase/Core 3.4.0

ライブラリのインストール

まずは必要なライブラリをインストールします
最近では Cocoapods を使って簡単にライブラリをインストールできます

  • vim Podfile
pod 'Firebase/Core'
pod 'Firebase/AdMob'
  • pod install

で OK です
インストールされたバージョンは冒頭の環境に記載されているバージョンでした

Firebase にプロジェクトおよびアプリを作成する

Firebase のコンソール にアクセスします
すでに Admob アカウントを持っている場合はそのアカウントでアクセスすると後々の設定が楽になります

アクセスしたらプロジェクトを作成しましょう
Google プロジェクトがすでにある場合はそこからインポートしても良いです
プロジェクトが作成できたら作成したプロジェクトを選択して、そのプロジェクトの中にアプリを作成しましょう
アプリは iOS のアプリを作成します
firebase_admob_creating_app.png

アプリを設定する画面になったら公開しているアプリの情報を入力しましょう
iTunes Connect とかで確認できるので入力してください
今回はすでに公開している自分のアプリに対して Admob を設定するので、その情報を入れましたがまだ公開していないアプリに設定したいケースもあると思います
その場合は iOS バンドル ID だけ公開予定のものを入れておけば OK です
あとは省略してください
firebase_admob_setting_app.png

GoogleService-Info.plist を入手する

上記の情報を入力して「アプリの追加」をクリックすると GoogleService-Info.plist というファイルがダウンロードできます
これをプロジェクトの直下にコピーしましょう
以下のような感じで配置すれば OK です
firebase_admob_copy_info_file.png

ファイルの中身は Admob で使用するテスト用の広告ユニット ID が記載されている他、Push Notification (GCM) の情報やデータストアの情報など Firebase を利用するための情報が XML 形式で記載されています

AppDelegate.swift で Firebase の初期化をする

さて、ここからは Xcode でプログラミングをしていきます
まずは Firebase を使うための初期化です
これは簡単で AppDelegate.swift に以下の 2 つ追記するだけです

import Firebase

import 文は冒頭に追記してください

FIRApp.configure()

上記メソッドは didFinishLaunchingWithOptions 内のどこかで宣言してください
心配であれば return true の前に追記すれば OK です
これで Firebase を使う準備ができました

GADBannerView を追加する

Storyboard を使って View を追加していきます
View を一つ追加して、更にその上に View を追加しましょう
オートレイアウトは各人の環境に併せて適当に設定してください
バナーをこの View に表示するので最低でも 50 以上にしておいてください
firebase_admob_insert_bannerview.png

そして追加した 2 つ目の View を CustomClass で GADBannerView にすれば OK です
firebase_admob_setting_gadbanner.png

GADBannerView を IBOutlet としてコードに追加する

Storyboard で追加した View をコードに紐付けます
Xcode 上で画面分割モードにして GADBannerView を選択して Ctrl を押しながらコード側にドラッグアンドドロップすれば OK です

名前は bannerView にしましょう
以下のような感じで swift ファイル側に追加できれば OK です

@IBOutlet weak var bannerView: GADBannerView!

GADBannerView に広告ユニット ID を設定する

コード側に追加した bannerView に広告ユニット ID を設定しましょう
viewDidLoad に以下を追記しましょう

import GoogleMobileAds

は冒頭に追記してください

override func viewDidLoad() {
    super.viewDidLoad()
    bannerView.adUnitID = "ca-app-pub-3940256099942544/2934735716"
    bannerView.adSize = kGADAdSizeSmartBannerPortrait
    bannerView.rootViewController = self
    bannerView.loadRequest(GADRequest())
}

上記で設定した広告ユニット ID は Admob が提供しているテスト用の ID になります
なので、本番で利用する広告ユニット ID を Admob の画面から取得しておきます
テスト用のユニット ID だと広告のサイズがバナーになっていないためかうまく表示されないことがあったので、アプリ用の ID を取得しておきます (どうせ、公開するときには変更しなければいけないので)

Admob にアクセスしたらログインします
ログインするユーザは Firebase と同じ Google アカウントにしたほうが良いです
「新しいアプリを収益化」からアプリを作成します
するとアプリの情報を入力する画面になるので入力していきます
ここでもまだアプリを公開していない場合は「アプリを手動で追加」からアプリを追加してください
firebase_admob_creating_admob_app.png

ポイントは 2 つ目の広告ユニットの設定でここで必ずバナー広告を選択するようにしてください
firebase_admob_setting_admob_app.png

アプリを作成すると本番で使用する広告ユニット ID が払い出されるので、コード側の bannerView.adUnitID に設定しましょう

ちょっとおまけ

GADBannerViewDelegate を継承して以下のメソッドを追加しておくと広告が取得できなかったときやうまく取得できたときのイベントを追えるのでデバッグしやすくなるかもしれません

// Admob から広告が取得できなかったときに呼ばれます
func adView(bannerView: GADBannerView!, didFailToReceiveAdWithError error: GADRequestError!) {
    print("didFailToReceiveAdWithError")
}

// Admob から広告が取得できたときに呼ばれます
func adViewDidReceiveAd(bannerView: GADBannerView!) {
    print("adViewDidReceiveAd")
}

また、その場合は bannerView の delegate に self を設定してください

bannerView.delegate = self

動作確認

では、アプリを起動してみます
今回は広告のタイプをバナーでサイズを kGADAdSizeSmartBannerPortrait というものにしています
これは動的にサイズを変更してくれる設定でスマホを縦にしたり横にしたりしても適切なサイズの広告を毎回取得してくれます
以下のような感じで表示されると思います


firebase_admob_ret_portrait.png


firebase_admob_ret_landscape.png

一応注意としては本番用の広告ユニット ID を使っているので、テストの状態で自分の実機などで広告をクリックするとアウトらしいので、クリックしないようにしてください

トラブルシューティング

  • STOP!! Will reset deviceID from memory.

となり広告が表示できないことがあった
対処方法としては Admob で広告を追加するときに広告タイプを「テキスト」「画像」の 2 つを表示しないとダメでした
はじめはテキストだけにしていたのですが、どうやらそれだと表示できないことがあるようです

  • NSLocalizedFailureReason=Request Error: No ad to show.

didFailToReceiveAdWithError メソッドがいつもコールされて広告が表示れない場合の対処ですが、コード上の設定や Storyboard 上の設定が何も間違っていなくそれでも上記のエラーが発生する場合は少し時間を置いて試してみましょう
Google Adsense 等もそうですが、広告がすぐに表示されないことがあります
自分の間隔だと 1 時間おけば確実に表示されます

最後に

iOS アプリに Firebase 版の Admob を導入する方法を紹介しました
基本つまづくことはなさそうですが、細かいところ (広告ユニットのサイズや広告ユニット ID を正しく設定するところなど) は若干ハマりそうな印象を受けました
それでも昔に比べたら格段に iOS アプリに広告を入れる方法は簡単になったと思います

あと、タイトルにもあるように今回は Xcode7 での手順です
Xcode8 だと追加の手順があるはずなので、それも検証して記事にできればと思います

参考リンク