React Nativeでの通知機能構築
Firebase Cloud Messaging(FCM)をReact Nativeアプリケーションで利用する場合、react-native-fcmは通知管理の包括的なソリューションを提供します。このモジュールは、遠隔プッシュとローカル通知の両方を統一的に扱い、開発者が効率的に通知関連機能を実装できるように支援します。
モジュールの初期設定と権限管理
通知機能を使用する前に、必要な権限の取得とプラットフォーム固有の初期化を行う必要があります。
import FCM from 'react-native-fcm';
// 通知権限のリクエスト
const requestNotificationPermission = async () => {
try {
const result = await FCM.requestAuthorization({
badge: true,
sound: true,
alert: true
});
console.log('権限リクエスト結果:', result);
} catch (error) {
console.error('権限取得エラー:', error);
}
};
// Androidの通知チャネル作成
const setupNotificationChannel = () => {
if (Platform.OS === 'android') {
FCM.createNotificationChannel({
id: 'general',
name: '一般通知',
description: 'アプリケーションの標準通知',
importance: 'high',
vibrate: true
});
}
};
// 初期化プロセス
const initializeNotifications = () => {
requestNotificationPermission();
setupNotificationChannel();
};
デバイストークンの取得と管理
サーバーへの通知送信には、デバイス固有のトークンが必要です。
// FCMトークンの取得と監視
const manageDeviceTokens = () => {
// 現在のFCMトークンを取得
FCM.getRegistrationToken().then(currentToken => {
if (currentToken) {
console.log('FCMトークン:', currentToken);
sendTokenToServer(currentToken);
}
});
// トークン更新の監視
this.tokenRefreshListener = FCM.onTokenRefresh(refreshedToken => {
console.log('トークンが更新されました:', refreshedToken);
updateServerToken(refreshedToken);
});
};
// iOS用APNSトークンの取得
const fetchAPNSToken = () => {
if (Platform.OS === 'ios') {
FCM.getAPNSToken().then(apnsToken => {
console.log('APNSトークン:', apnsToken);
});
}
};
// サーバーへのトークン送信関数
const sendTokenToServer = (token) => {
// ここでサーバーAPIを呼び出してトークンを登録
fetch('https://your-server.com/register-device', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ deviceToken: token })
});
};
通知の受信と処理
アプリケーションの状態に応じて、異なる方法で通知を受信・処理します。
起動時の通知取得
// アプリが通知から起動された場合の処理
const handleInitialNotification = async () => {
const initialNotification = await FCM.getInitialNotification();
if (initialNotification) {
console.log('起動通知:', initialNotification);
// 通知内容に基づくナビゲーション処理
if (initialNotification.screen) {
navigateToScreen(initialNotification.screen, initialNotification.data);
}
}
};
実行中の通知監視
// 通知イベントリスナーの設定
const setupNotificationListeners = () => {
// 通知受信リスナー
this.notificationListener = FCM.onNotification(notification => {
console.log('通知受信:', notification);
// アプリがフォアグラウンドにあるかどうかの判定
if (notification.foreground) {
// フォアグラウンド時の処理(例: ローカル通知の表示)
displayInAppNotification(notification);
} else {
// バックグラウンドまたはアプリ未起動時の処理
handleBackgroundNotification(notification);
}
});
// 通知クリックリスナー
this.notificationOpenedListener = FCM.onNotificationOpened(notification => {
console.log('通知が開かれました:', notification);
handleNotificationTap(notification);
});
};
// 通知リスナーのクリーンアップ
const cleanupNotificationListeners = () => {
if (this.notificationListener) {
this.notificationListener.remove();
}
if (this.notificationOpenedListener) {
this.notificationOpenedListener.remove();
}
if (this.tokenRefreshListener) {
this.tokenRefreshListener.remove();
}
};
ローカル通知の実装
アプリケーション内部からローカル通知を生成する方法を説明します。
// 即時ローカル通知の表示
const showImmediateNotification = (notificationData) => {
const notificationDetails = {
channel: 'general',
title: notificationData.title || '新着通知',
body: notificationData.message || '',
priority: 'high',
small_icon: 'ic_notification',
large_icon: 'ic_launcher',
color: '#2196F3',
vibrate: 300,
lights: true,
sound: 'default'
};
FCM.showLocalNotification(notificationDetails);
};
// スケジュールされたローカル通知
const scheduleNotification = () => {
const scheduledTime = new Date().getTime() + (10 * :00); // 10分後
FCM.scheduleLocalNotification({
id: 'reminder_001',
fire_date: scheduledTime,
title: 'リマインダー',
body: '設定した時間になりました',
repeat_interval: 'day', // 日次繰り返し
data: { type: 'reminder', id: 'task_123' }
});
};
// インタラクティブな通知(アクションボタン付き)
const createInteractiveNotification = () => {
const actionButtons = [
{ id: 'confirm', title: '確認', foreground: true },
{ id: 'cancel', title: 'キャンセル', destructive: true }
];
FCM.showLocalNotification({
title: '確認が必要です',
body: 'この操作を実行しますか?',
actions: actionButtons,
category: 'confirmation'
});
};
カスタムメッセージ処理と応用例
標準的な通知以外にも、さまざまな形式のメッセージを処理できます。
// データメッセージの処理(通知表示なし)
const handleDataMessage = (message) => {
console.log('データメッセージ受信:', message);
// メッセージタイプに基づく処理
switch (message.type) {
case 'data_update':
refreshApplicationData(message.payload);
break;
case 'config_update':
updateAppConfiguration(message.settings);
break;
case 'silent_notification':
// バックグラウンド処理を実行
performBackgroundTask(message.task);
break;
default:
console.log('未知のメッセージタイプ:', message.type);
}
};
// カスタム通知イベントハンドラ
const setupCustomHandlers = () => {
// 通知アクションボタンクリックの処理
FCM.onNotificationAction((actionId, notification) => {
console.log(`アクション "${actionId}" がクリックされました`);
switch (actionId) {
case 'confirm':
handleConfirmationAction(notification.data);
break;
case 'cancel':
handleCancellationAction(notification.data);
break;
case 'view':
navigateToDetails(notification.data);
break;
}
});
};
// 通知のカテゴリ別管理
const categorizeNotifications = () => {
// 複数の通知チャネル作成
const channels = [
{
id: 'messages',
name: 'メッセージ',
importance: 'high',
description: 'チャットメッセージの通知'
},
{
id: 'alerts',
name: 'アラート',
importance: 'max',
description: '重要なアラート通知'
},
{
id: 'promotions',
name: 'プロモーション',
importance: 'low',
description: 'プロモーション関連の通知'
}
];
channels.forEach(channel => {
FCM.createNotificationChannel(channel);
});
};
実装上の考慮点とベストプラクティス
- 適切なエラーハンドリングを実装し、ネットワーク接続の問題や権限エラーに対処する
- アプリケーションのライフサイクルイベント(アプリの一時停止、再開など)で通知リスナーを適切に管理する
- プラットフォーム固有の動作(iOSの通知権限ダイアログ、Androidの通知チャネルなど)を理解する
- ユーザーの通知設定を尊重し、オプトアウトの仕組みを提供する
- 通知の重複を防ぐため、適切な通知ID管理を行う