技術
約3分で読めます
Firebase FCM プッシュ通知の実装ガイド(WebView + Android)
これは2025年の夏頃に別案件で実装した内容。ブログ移転前だったので記事にしてなかった(はず)。忘れないうちにまとめておく。
WebViewベースのAndroidアプリにプッシュ通知を実装したときの話。
FCMの基本概念
FCMトークンとは
Firebaseが端末ごとに自動生成する識別子。ユーザーIDから生成されるものではなく、端末固有のもの。アプリの再インストールや一定期間で変わる可能性がある。
必要なデータ
プッシュ通知に必要なのは「ユーザーID + FCMトークン」のみ。メールアドレスは通知内容のパーソナライズ用で、必須ではない。
実装の全体像
1. Web側でユーザー作成 → ユーザーID発行
2. アプリ側にユーザーIDを渡す(JavaScript Interface経由)
3. アプリ側でFCMトークン取得
4. ユーザーID + FCMトークン をサーバーに送信・DB保存
役割分担
| 役割 | 担当 |
|---|---|
| ユーザー管理・認証 | Web側 |
| ビジネスロジック | Web側 |
| 通知送信の判断(いつ・誰に・何を) | Web側(サーバー) |
| FCMトークン取得 | アプリ側 |
| 通知の受信・表示 | アプリ側 |
アプリは「WebViewの器 + 通知機能」だけ。メインの仕事場はWeb側。
サーバー側実装(PHP)
FCMトークンの保存
Firebase上に保存する必要はなく、自前のDBでOK。
CREATE TABLE user_fcm_tokens (
user_id VARCHAR(255),
fcm_token VARCHAR(500),
created_at TIMESTAMP
);
ライブラリのインストール
composer require kreait/firebase-php
個別通知の送信
use Kreait\Firebase\Factory;
use Kreait\Firebase\Messaging\CloudMessage;
class NotificationService
{
private $messaging;
public function __construct() {
$factory = (new Factory)
->withServiceAccount('/path/to/service-account.json');
$this->messaging = $factory->createMessaging();
}
public function sendToUser($userId, $title, $body) {
$fcmToken = $this->getUserFcmToken($userId);
if (!$fcmToken) {
throw new Exception('FCM token not found');
}
$message = CloudMessage::withTarget('token', $fcmToken)
->withNotification([
'title' => $title,
'body' => $body,
])
->withData([
'userId' => $userId,
'type' => 'message'
]);
return $this->messaging->send($message);
}
}
全体通知(トピック機能)
1回のAPI呼び出しで全ユーザーに送信できる。
// トークン登録時にトピックにも登録
public function registerToken($userId, $fcmToken) {
$this->saveUserToken($userId, $fcmToken);
$this->messaging->subscribeToTopic('all_users', [$fcmToken]);
}
// 全体通知送信
public function sendToAllUsers($title, $body) {
$message = CloudMessage::withTarget('topic', 'all_users')
->withNotification([
'title' => $title,
'body' => $body
]);
return $this->messaging->send($message);
}
Android側実装
Firebase Consoleでの準備
- Firebase Consoleでプロジェクト作成
google-services.jsonをダウンロードしてapp/に配置
Gradle設定
// app/build.gradle
dependencies {
implementation 'com.google.firebase:firebase-messaging:23.0.0'
}
MainActivityの実装
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setupWebView()
}
// Web側から呼ばれるJavaScript Interface
@JavascriptInterface
fun registerUser(userId: String) {
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (task.isSuccessful) {
val fcmToken = task.result
// サーバーに送信
sendToServer(userId, fcmToken)
// 全体通知用トピックに登録
FirebaseMessaging.getInstance().subscribeToTopic("all_users")
}
}
}
private fun sendToServer(userId: String, fcmToken: String) {
// HTTP POST でサーバーに送信(OkHttp等使用)
}
private fun setupWebView() {
webView.settings.javaScriptEnabled = true
webView.addJavascriptInterface(this, "Android")
webView.loadUrl("https://yourwebapp.com")
}
}
Web側からの呼び出し
// ユーザー登録完了時にアプリ側に通知
if (window.Android) {
window.Android.registerUser(userId);
}
注意点
- トークンの更新: FCMトークンは定期的に更新されるため、更新処理も実装する
- ネイティブ実装を推奨: WebView内でのFCMは制限があるため、ネイティブ側でFCM実装が確実
- 許可の取得: プッシュ通知の許可をユーザーから取得する必要がある
- トピック名の形式:
/topics/[a-zA-Z0-9-_.~%]+の形式 - トピック数の上限: 1アプリで最大2000万トピック
作業工程の目安
| 作業 | 時間 |
|---|---|
| Firebase Console でプロジェクト作成 | 5分 |
| google-services.json ダウンロード | 1分 |
| Gradle設定 | 2分 |
| コード実装 | 30分 |
| 合計 | 約1時間 |
シンプルなプッシュ通知なら1時間程度で実装できる。