はじめに
Flutterアプリケーションでカスタムビジネスロジックを実装する場合、バックエンドとしてFirebase Functionsを使用することが非常に有効です。Firebase Functionsは、クラウド上でバックエンドロジックを実行できるサーバーレスなソリューションで、特定のイベントに応じた処理や、複雑な計算、API連携などを行うことができます。
本記事では、FlutterアプリケーションとFirebase Functionsを連携し、カスタムビジネスロジックを実装するための基本的な手順を解説します。エンジニア初心者でも理解しやすいように、環境設定から実装、テストまでを順を追って説明します。
⚠️ 注意: Functionsを使うにはFirebaseのプランを従量課金制にする必要があります。
Firebase Functions とは?
Firebase Functionsは、特定のイベント(HTTPリクエストやFirebaseのデータ変更)をトリガーとして、カスタムロジックを実行できるクラウドベースのサービスです。サーバーの設定や管理を行う必要がなく、特定のバックエンド処理をクラウドで効率的に処理できます。
Firebase Functions の主な特徴
- サーバーレス:サーバー管理が不要で、スケーラブルな処理を自動的に実行。
- イベント駆動:FirestoreやAuthentication、Storageのイベントをトリガーに処理を実行。
- HTTPリクエスト:HTTPリクエストをトリガーにカスタムAPIのように利用可能。
環境構築
Firebase プロジェクトの作成
まずは、Firebaseコンソールで新しいプロジェクトを作成します。すでにFirebaseプロジェクトがある場合は、次のステップに進んでください。
Firebaseプロジェクトの作成・プロジェクトの初期化はこちらの記事で説明しています。
Firebase Authenticationのセットアップの手順後に続きを実施してください
(Firebase Authenticationを有効にする必要はありません)

Firebase functionsの設定
FlutterプロジェクトディレクトリでFirebase functionsの設定を行います。
firebase init functions
初期化中に、次のようなオプションを選択します:
- Functionsの言語:JavaScriptまたはTypeScriptを選択(今回はJavaScriptで進めます)。
- ESLint:コードの静的解析を行いたい場合は「はい」。
これで、functions/
ディレクトリが生成され、Firebase Functionsを使用できるようになります。
Firebase Functions の実装
基本的なHTTP関数の実装
Firebase Functionsでは、HTTPリクエストをトリガーにする関数を簡単に実装できます。以下のコードは、HTTPリクエストに対して「Hello World」を返すシンプルな関数です。
const functions = require('firebase-functions');
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase Functions!");
});
カスタムビジネスロジックの実装
次に、カスタムビジネスロジックを実装します。例えば、Flutterアプリから送信されたデータを処理し、その結果を返すAPIを作成します。
以下の例では、JSON形式のデータを受け取り、特定のビジネスロジックを適用して結果を返す関数を実装しています。
exports.calculateDiscount = functions.https.onRequest((req, res) => {
const data = req.body;
// データに基づいてカスタムロジックを実行
const discount = data.price * 0.1; // 10%割引を計算
// 結果をJSONで返す
res.json({
originalPrice: data.price,
discountPrice: data.price - discount
});
});
デプロイ
関数の実装が完了したら、Firebaseにデプロイします。
cd functions
npm run deploy
デプロイが完了すると、指定した関数が利用可能になります。関数のURLはFirebaseのコンソールやデプロイログで確認できます。
もし失敗する場合、firebase.json
のにbuildコマンドとlintコマンドの実行設定がされている場合があるので今回は削除します。
{
"functions": [
{
"source": "functions",
"codebase": "default",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log",
"*.local"
],
// ここを修正
"predeploy": []
}
]
}
Flutter との連携
HTTPパッケージのインストール
FlutterアプリからFirebase Functionsを呼び出すためには、http
パッケージを使用します。pubspec.yaml
に以下を追加し、パッケージをインストールします。
dependencies:
http: ^0.13.3
flutter pub get
Firebase Functions の呼び出し
FlutterアプリからFirebase Functionsのカスタムロジックを呼び出し、データを送信してその結果を取得するコードを実装します。
import 'package:http/http.dart' as http;
import 'dart:convert';
class FirebaseService {
Future<void> getDiscountPrice(double price) async {
final url = Uri.parse('cloudfunctionsのトリガー欄に記載のurl');
final response = await http.post(
url,
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'price': price}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
print('Original Price: ${data['originalPrice']}');
print('Discount Price: ${data['discountPrice']}');
} else {
throw Exception('Failed to get discount price');
}
}
}
UIに連携
FlutterのUIで、価格を入力して割引価格を計算する簡単な画面を作成します。
import 'package:flutter/material.dart';
import 'firebase_service.dart';
class DiscountScreen extends StatefulWidget {
@override
_DiscountScreenState createState() => _DiscountScreenState();
}
class _DiscountScreenState extends State<DiscountScreen> {
final FirebaseService _firebaseService = FirebaseService();
final TextEditingController _priceController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Calculate Discount')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
controller: _priceController,
decoration: InputDecoration(labelText: 'Enter price'),
keyboardType: TextInputType.number,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
final price = double.parse(_priceController.text);
await _firebaseService.getDiscountPrice(price);
},
child: Text('Get Discount'),
),
],
),
),
);
}
}
今回のコードの全貌
functions/index.js
const functions = require('firebase-functions');
exports.calculateDiscount = functions.https.onRequest((req, res) => {
const data = req.body;
// データに基づいてカスタムロジックを実行
const discount = data.price * 0.1; // 10%割引を計算
// 結果をJSONで返す
res.json({
originalPrice: data.price,
discountPrice: data.price - discount
});
});
lib/main.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() async {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: DiscountScreen(),
);
}
}
class DiscountScreen extends StatefulWidget {
@override
_DiscountScreenState createState() => _DiscountScreenState();
}
class _DiscountScreenState extends State<DiscountScreen> {
final FirebaseService _firebaseService = FirebaseService();
final TextEditingController _priceController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Calculate Discount')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
controller: _priceController,
decoration: InputDecoration(labelText: 'Enter price'),
keyboardType: TextInputType.number,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
final price = double.parse(_priceController.text);
await _firebaseService.getDiscountPrice(price);
},
child: Text('Get Discount'),
),
],
),
),
);
}
}
class FirebaseService {
Future<void> getDiscountPrice(double price) async {
print(price);
// final url = Uri.parse('https://flutter-app-b5408.cloudfunctions.net/calculateDiscount');
final url = Uri.parse('https://calculatediscount-d6nzowqehq-uc.a.run.app');
final response = await http.post(
url,
headers: {'Content-Type': 'application/json'},
body: jsonEncode({'price': price}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
print('Original Price: ${data['originalPrice']}');
print('Discount Price: ${data['discountPrice']}');
} else {
throw Exception('Failed to get discount price');
}
}
}
実行結果
コンソールで下記が表示されていたら成功

まとめ
この記事では、FlutterアプリケーションでFirebase Functionsを使い、カスタムビジネスロジックを実装する手順を解説しました。Firebase Functionsは、サーバーレスで簡単にバックエンドの処理を実装できるため、アプリの拡張性や柔軟性が向上します。
この記事のポイント:
- Firebase Functionsを使ったカスタムビジネスロジックの実装
- FlutterアプリとFirebase Functionsの連携方法
- カスタムAPIの構築とデプロイ
Firebase FunctionsとFlutterを組み合わせることで、より複雑でパワフルなアプリケーションを構築できるようになります。今後は、さらに高度なロジックやデータ処理を取り入れて、アプリを発展させましょう。
コメント