iOSの16.4からWebプッシュに対応しました。
AWSのブログでも紹介されていた記事を参考にAmplifyで作成したアプリでWebプッシュを試してみました。
詳細な手順は個人ブログで紹介しています。
Firebaseプロジェクトの作成
「AmplifyでWebプッシュ」といってますが、AmplifyやPinpoint単体では通知を行うことはできず、通知には外部サービスに頼る必要があります。
Firebase Cloud Messagingを使用すると、PinpointからはAndroidにプッシュする感覚でWebプッシュが行なえます。
Firebase consoleでプロジェクトを作成し、Firebase Cloud Messagingを有効化します。
Firebaseプロジェクトの作成を参考になんやかんや設定をして、以下の3点を入手します。
- SDK の設定と構成のConfig
- サーバーキー
- 鍵ペア
AmplifyのAuthとAnalyticsを追加
amplify add auth
amplify add analytics
amplify push
このサクサク感、病みつきになりますよね
Amazon PinpointにFirebase Messagingのキーを登録
マネジメントコンソールを使用しないといけないのが残念ですが我慢しましょう。Firebase Cloud Messagingで取得したサーバーキー
を登録します。
Service Workerを作成
Webプッシュを受けるのはService Workerです。
push
とnotificationclick
のイベントリスナーを用意します。
addEventListener('push', (event) => {
console.log('[Service Worker] Push Received.');
console.log(`[Service Worker] Push had this data: "${event}"`);
if (!(self.Notification && self.Notification.permission === 'granted'))
return;
var data = {};
if (event.data)
data = event.data.json();
console.log(data)
var title = data.data['pinpoint.notification.title'];
var message = data.data['pinpoint.notification.body'];
var icon = data.data['pinpoint.notification.imageIconUrl'];
var image = data.data['pinpoint.notification.imageUrl'];
var options = {
body: message,
icon: icon,
image: image,
data: data
};
event.waitUntil(self.registration.showNotification(title, options));
});
addEventListener('notificationclick', (event) => {
console.log('[Service Worker] Notification click: ', event);
event.notification.close();
event.waitUntil(
clients.openWindow(event.notification.data.data['pinpoint.url'])
);
});
Appのコードを準備
Firebase Cloud Messagingの初期化
import { initializeApp } from "firebase/app";
import { getMessaging } from "firebase/messaging";
const firebaseConfig = {
apiKey: "AIzaSyDjcpgUOkQKYsfahsBx-pd5rRNLMu8e2OI",
authDomain: "webpush-6b963.firebaseapp.com",
projectId: "webpush-6b963",
storageBucket: "webpush-6b963.appspot.com",
messagingSenderId: "849385313410",
appId: "1:849385313410:web:75afe5212cc8a264da109b"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// Initialize Firebase Cloud Messaging and get a reference to the service
const messaging = getMessaging(app);
鍵ペアの定義
const vapidKey = "BCYBsbttg4lKsLkSz3KXHdoijEKJhLWj7Au69Sp9niUUa_IwRtXAYSd7zLP52hBKG-_uf8evUTVphiMKl4CNihk"
Service Workerの登録
import { ServiceWorker } from 'aws-amplify';
const serviceWorker = new ServiceWorker()
var registration: ServiceWorkerRegistration;
serviceWorker.register('/service-worker.js', '/').then((reg => registration = reg as ServiceWorkerRegistration))
AmplifyとFirebaseのキメラ感がすごい
権限の許可を要求
こんなやつを出します。
import { getToken } from "firebase/messaging";
function requestPermission() {
isSupported().then((isSupport) => {
if (!isSupport) {
console.log('Messaging is not support.');
return
}
console.log('Requesting permission...');
Notification.requestPermission().then((permission) => {
if (permission === 'granted') {
console.log('Notification permission granted.');
getTokenRequest()
}
})
})
}
デバイストークンの取得
公開鍵からデバイスごとのトークンを生成します。
import { getToken } from "firebase/messaging";
function getTokenRequest() {
// Add the public key generated from the console here.
getToken(messaging, {
vapidKey: vapidKey,
serviceWorkerRegistration: registration
})
.then((currentToken) => {
if (currentToken) {
// Send the token to your server and update the UI if necessary
// ...
console.log(`token: ${currentToken}`);
setDeviceToken(currentToken)
} else {
// Show permission request UI
console.log('No registration token available. Request permission to generate one.');
// ...
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
// ...
});
}
デバイストークンをAmazon Pinpointに登録
import { Analytics } from 'aws-amplify';
Analytics.updateEndpoint({
address: deviceToken,
channelType: "GCM",
optOut: 'NONE',
}).then((reason => { console.log(reason) }))
通知を送信
1:1で送信するケース
サーバー側で長時間処理をして、処理完了を通知したいケースです。この場合は、PinpointのsendMessages APIを使用します。
body.token
がデバイストークンです。
await sleep(5000)
const params = {
ApplicationId: applicationId,
MessageRequest: {
"Addresses": {
[body.token]: {
"ChannelType": "GCM"
}
},
"Endpoints": {},
"MessageConfiguration": {
"GCMMessage": {
"Title": "Push Title",
"Action": "URL",
"Body": "Body Message",
"ImageUrl": "https://placekitten.com/200/300",
"ImageIconUrl": "https://placekitten.com/g/96/96",
"Url": body.url || 'http://localhost:8080'
}
}
}
}
const res = await pinpoint.sendMessages(params).promise()
通知が来ました。
キャンペーンの通知
多数に一斉に通知をしたい場合はこちらのケース。
セグメントを作成し、キャンペーンとして通知します。
iPhoneへの通知
さて、iPhoneへの通知については1つ注意点があり、ユーザーがPWAとしてインストールする必要があります
ます。
PWAとしてインストールした状態で通知を受信することができました。
詳細な手順は個人ブログで紹介しています。