技術 約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での準備

  1. Firebase Consoleでプロジェクト作成
  2. 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時間程度で実装できる。