はじめに
ライセンスの期限チェックやゲームの時間チート対策など、端末の日時ではなくサーバの日時が欲しいケースがあります。
Google Firebaseの1機能であるCloud Functions for Firebaseを使うことで、容易にサーバ日時取得処理をアプリに追加できます。
Cloud Functions for Firebaseとは
アプリなどの環境から、Googleクラウド上にデプロイしているバックエンドコードを実行することができる機能です。
毎月200万回、処理時間100万秒、トラフィック容量5GBまでであれば無料で利用できます。2019/7/10現在
前提条件
この記事を利用するにあたり、次の状態を前提とします。
- 処理を追加するXcodeプロジェクトが存在する
- Google Firebase上にプロジェクトを作成し、Xcodeプロジェクトに導入している
- XcodeプロジェクトにCocoaPodsからFirebaseを導入している
- Xcodeプロジェクトで、Firebaseの初期化処理を実装している
CocoaPodsを使っていない場合など環境が異なる場合は、記事の該当部分について適宜対応してください。
環境の構築
上の項目から順番にインストールしていきます。
すでにインストール済みの場合、スキップして次の項目に移ってください。
Node.jsとnpmのインストール
Node.js公式サイトにアクセスし、インストーラーをダウンロードしインストールします。
インストール後ターミナルで次のコマンドを入力し、バージョン情報を得られたらインストール完了です。
$ node --version
$ npm --version
Firebase CLIのインストール
ターミナルで次のコマンドを入力し、Firebase CLIをインストールします。
$ npm install -g firebase-tools
バックエンド側の実装
プロジェクトの作成
管理しやすい場所(Xcodeプロジェクトフォルダの直下など)に適当なフォルダを作成します。(以降バックエンドフォルダ)
$ mkdir FirebaseFunctions
ターミナルで作成したフォルダに移動し、次のコマンドを入力します。
$ firebase init
実行するといくつか選択項目が表示されるので、次の値を選択します。
- 利用する機能:Functions: Configure and deploy Cloud Functions
- デフォルトのFirebaseプロジェクト:作成したFirebaseプロジェクトを選択します
- 言語:JavaScript
- ESLintを利用するか:好みで選択します。単純な機能を実装するため、Nで問題ありません
- 今すぐ依存関係をインストールするか:Y
以上の手順でバックエンドフォルダ直下にファイル一式が作成されます。
コードの記述
サーバ日時を取得するためのコードを記述します。
バックエンドフォルダ/functions/index.js に次のコードを追加します。
exports.ServerTime = functions.https.onRequest((request, response) => {
var dt = new Date();
var delta = dt.getTime();
response.send({
data: String(delta)
});
});
コードのデプロイ
ターミナルで次のコマンドを入力し、ログインします。
$ firebase login
ログインしている状態で次のコマンドを入力し、デプロイを実行します。
$ firebase deploy
Deploy complete!と表示されたらデプロイ完了です。
ターミナルに出力されたProject ConsoleのURLを開き、Functionsからデプロイした関数を確認できます。
Xcodeプロジェクト側の実装
SDKのインストール
CocoaPodsからFirebaseFunctionsをインストールします。
podfileに次の行を追記します。
pod 'Firebase/Functions'
追記後ターミナルで次のコマンドを入力し、インストールを実行します。
$ pod install
サーバ日時取得処理の実装
この記事ではサンプルとして、アプリ起動時にサーバ日時を取得しログ出力するよう実装します。
ViewController.swiftに次のコードを記述します。
import FirebaseFunctions
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let functions = Functions.functions()
functions.httpsCallable("ServerTime").call { result, error in
if let error = error {
debugPrint(error.localizedDescription)
} else {
if let data = result?.data as? String {
let ms = UInt64(data) ?? 0
let timeInterval = TimeInterval(ms) * 0.001
let date = Date(timeIntervalSince1970: timeInterval)
debugPrint("サーバ日時: \(date.description(with: Locale.current))")
} else {
debugPrint("受信データなし")
}
}
}
}
}
実行し、次のようなログが出力されれば成功です。
"サーバ日時: Wednesday, July 10, 2019 21:02:43 Japan Standard Time"
メモ
サーバ日時はミリ秒で得られる為、Date型に変換する際は0.001を掛けて秒に変換する必要があります。
久しぶりにコードのメンテナンスを行おうとしたところ、firebase init
で失敗する現象に遭遇しました。
コンソールから再ログインを行う事で解決しました。
$ firebase logout
$ firebase login