إذا سألت مجموعة من المطوّرين عن الميزات التي لا تتوفر على الويب والتي تتوفر على الأجهزة الجوّالة، ستظهر الإشعارات الفورية دائمًا في أعلى القائمة.
تتيح الإشعارات الفورية للمستخدمين الموافقة على تلقّي آخر الأخبار في الوقت المناسب من المواقع الإلكترونية التي يحبونها، كما تتيح لك إعادة جذبهم بفعالية من خلال محتوى مخصّص وجذاب.
اعتبارًا من الإصدار 42 من Chrome، أصبحت واجهتا برمجة التطبيقات Push API وNotification API متاحة للمطوّرين.
تعتمد Push API في Chrome على بعض التقنيات المختلفة، بما في ذلك ملفات بيان تطبيقات الويب وخدمات العمال. في هذه المشاركة، سنلقي نظرة على كلّ من هذه التقنيات، ولكن فقط الحدّ الأدنى لإعداد رسائل الإشعارات الفورية وتشغيلها. لفهم بعض الميزات الأخرى للملفات البيانية وإمكانات الخدمة بلا إنترنت، يُرجى الاطّلاع على الروابط أعلاه.
سنلقي أيضًا نظرة على الميزات التي ستتم إضافتها إلى واجهة برمجة التطبيقات في الإصدارات المستقبلية من Chrome، وأخيرًا سنقدّم لك قائمة بالأسئلة الشائعة.
تنفيذ ميزة "الرسائل الفورية" في Chrome
يوضّح هذا القسم كل خطوة يجب إكمالها لتفعيل رسائل الدفع في تطبيق الويب.
تسجيل مشغّل خدمة
يجب توفُّر عامل خدمة لتنفيذ الرسائل الفورية على الويب. ويعود السبب في ذلك إلى أنّه عند تلقّي رسالة دفع، يمكن للمتصفّح بدء عامل خدمة يعمل في الخلفية بدون فتح صفحة، ويُرسِل حدثًا حتى تتمكّن من تحديد كيفية التعامل مع رسالة الدفع هذه.
في ما يلي مثال على كيفية تسجيل عامل خدمة في تطبيق الويب. عند اكتمال تسجيله بنجاح، نُجري initialiseState()، وسنتناوله قريبًا.
var isPushEnabled = false;
…
window.addEventListener('load', function() {
var pushButton = document.querySelector('.js-push-button');
pushButton.addEventListener('click', function() {
if (isPushEnabled) {
unsubscribe();
} else {
subscribe();
}
});
// Check that service workers are supported, if so, progressively
// enhance and add push messaging support, otherwise continue without it.
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(initialiseState);
} else {
console.warn('Service workers aren\'t supported in this browser.');
}
});
يشترك معالِج النقر على الزر في الرسائل الفورية أو يُلغي اشتراك المستخدم فيها. isPushEnabled هو متغيّر عام يتتبّع ببساطة ما إذا كان اشتراك الرسائل الفورية مفعّلاً حاليًا أم لا. وسيتم الإشارة إليها في جميع مقتطفات الرموز البرمجية.
بعد ذلك، نتحقّق من توفّر مشغّلات الخدمات قبل تسجيل service-worker.js
الملف الذي يحتوي على منطق معالجة رسالة فورية. هنا، نُعلم المتصفّح ببساطة أنّ ملف JavaScript هذا هو عامل الخدمة
لموقعنا الإلكتروني.
إعداد الحالة الأولية
بعد تسجيل الخدمة، علينا إعداد حالة واجهة المستخدم.
سيتوقع المستخدمون واجهة مستخدم بسيطة لتفعيل رسائل الإشعارات الفورية أو إيقافها لموقعك الإلكتروني، وسيتوقعون أن تكون هذه الواجهة محدّثة باستمرار لتتضمّن أي تغييرات تحدث. بعبارة أخرى، إذا فعّل المستخدمون رسائل الإشعارات الفورية لموقعك الإلكتروني، يمكنك الخروج من التطبيق والعودة بعد أسبوع، ومن المفترض أن يُبرز واجهة المستخدم أنّ رسائل الإشعارات الفورية مفعّلة.
يمكنك الاطّلاع على بعض إرشادات تجربة المستخدم في هذا المستند، وسنركّز في هذه المقالة على الجوانب الفنية.
في هذه المرحلة، قد تعتقد أنّ هناك حالتَين فقط للتعامل معهما، مفعّل أو غير مفعّل. ومع ذلك، هناك بعض الحالات الأخرى المتعلّقة بالإشعارات التي يجب أخذها في الاعتبار.
هناك عدد من واجهات برمجة التطبيقات التي يجب التحقّق منها قبل تفعيل الزر، و إذا كانت كل العناصر متوافقة، يمكننا تفعيل واجهة المستخدم وضبط الحالة الأولية لتحديد ما إذا كان قد تم الاشتراك في خدمة تلقّي الرسائل الفورية أم لا.
بما أنّ معظم عمليات التحقّق هذه تؤدي إلى إيقاف واجهة المستخدم، عليك ضبط الحالة الأولية على "متوقف". ويساعد ذلك أيضًا في تجنُّب أي التباس في حال حدثت مشكلة في JavaScript في صفحتك، على سبيل المثال، إذا تعذّر تنزيل ملف JS أو أوقف المستخدم JavaScript.
<button class="js-push-button" disabled>
Enable Push Messages
</button>
باستخدام هذه الحالة الأولية، يمكننا إجراء عمليات التحقّق الموضّحة أعلاه في الأسلوب
initialiseState()
، أي بعد تسجيل عامل الخدمة.
// Once the service worker is registered set the initial state
function initialiseState() {
// Are Notifications supported in the service worker?
if (!('showNotification' in ServiceWorkerRegistration.prototype)) {
console.warn('Notifications aren\'t supported.');
return;
}
// Check the current Notification permission.
// If its denied, it's a permanent block until the
// user changes the permission
if (Notification.permission === 'denied') {
console.warn('The user has blocked notifications.');
return;
}
// Check if push messaging is supported
if (!('PushManager' in window)) {
console.warn('Push messaging isn\'t supported.');
return;
}
// We need the service worker registration to check for a subscription
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
// Do we already have a push message subscription?
serviceWorkerRegistration.pushManager.getSubscription()
.then(function(subscription) {
// Enable any UI which subscribes / unsubscribes from
// push messages.
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = false;
if (!subscription) {
// We aren't subscribed to push, so set UI
// to allow the user to enable push
return;
}
// Keep your server in sync with the latest subscriptionId
sendSubscriptionToServer(subscription);
// Set your UI to show they have subscribed for
// push messages
pushButton.textContent = 'Disable Push Messages';
isPushEnabled = true;
})
.catch(function(err) {
console.warn('Error during getSubscription()', err);
});
});
}
في ما يلي نظرة عامة موجزة على هذه الخطوات:
- نتحقّق من توفّر
showNotification
في ServiceWorkerRegistration النموذج الأولي. بدون هذا الإذن، لن نتمكّن من عرض إشعار من الخدمة العاملة عند تلقّي رسالة فورية. - نتحقّق من قيمة
Notification.permission
الحالية للتأكّد من أنّها ليست"denied"
. يعني الرفض أنّه لا يمكنك عرض الإشعارات إلى أن يغيّر المستخدم الإذن يدويًا في المتصفّح. - للتحقّق مما إذا كانت ميزة المراسلة الفورية متاحة، نتحقق من توفّر
PushManager
في عنصر النافذة. - أخيرًا، استخدمنا
pushManager.getSubscription()
للتحقّق مما إذا كان لدينا اشتراك حاليًا أم لا. وفي حال حدوث ذلك، نرسل تفاصيل الاشتراك إلى الخادم لضمان حصولنا على المعلومات الصحيحة وضبط واجهة المستخدم للإشارة إلى ما إذا كانت ميزة "الرسائل الفورية" مفعّلة أم لا. سنطّلع على التفاصيل التي تظهر في عنصر الاشتراك لاحقًا في هذه المقالة.
ننتظر إلى أن يتم حلّ المشكلة navigator.serviceWorker.ready
للتحقّق من اشتراكك وتفعيل زر الدفع الفوري، لأنّه لا يمكنك الاشتراك في الرسائل الفورية إلا بعد تفعيل الخدمة.
الخطوة التالية هي معالجة الحالات التي يريد فيها المستخدم تفعيل رسائل الإشعارات الفورية، ولكن قبل أن نتمكّن من إجراء ذلك، علينا إعداد مشروع على Google Developers Console وإضافة بعض المَعلمات إلى البيان لكي تتمكّن من استخدام خدمة المراسلة عبر السحابة الإلكترونية من Firebase (FCM)، المعروفة سابقًا باسم "خدمة المراسلة عبر السحابة الإلكترونية من Google" (GCM).
إنشاء مشروع في "وحدة تحكّم مطوّري Firebase"
يستخدم Chrome خدمة "المراسلة عبر السحابة الإلكترونية من Firebase" (FCM) لمعالجة إرسال الرسائل الفورية وتسليمها. ومع ذلك، لاستخدام واجهة برمجة التطبيقات FCM API، عليك إعداد مشروع على "وحدة تحكّم مطوّري Firebase".
الخطوات التالية خاصة بمتصفّح Chrome وOpera لنظام التشغيل Android وSamsung Browser التي تستخدم إطار عمل Firebase للرسائل. سنناقش آلية عمل هذه الميزة في المتصفّحات الأخرى لاحقًا في المقالة.
إنشاء مشروع مطوّر جديد على Firebase
في البداية، عليك إنشاء مشروع جديد على https://console.firebase.google.com/ من خلال النقر على "إنشاء مشروع جديد".
أضِف اسمًا للمشروع وأنشئ المشروع، وسيتم نقلك إلى لوحة تحكم المشروع:
من لوحة البيانات هذه، انقر على الترس بجانب اسم مشروعك في أعلى الزاوية اليسرى وانقر على "إعدادات المشروع".
في صفحة الإعدادات، انقر على علامة التبويب "الرسائل عبر السحابة الإلكترونية".
تحتوي هذه الصفحة على مفتاح واجهة برمجة التطبيقات للرسائل الفورية، والذي سنستخدمه لاحقًا، رقم تعريف المُرسِل الذي يجب إدخاله في بيان تطبيق الويب في القسم التالي.
إضافة بيان تطبيق ويب
بالنسبة إلى الإشعارات الفورية، يجب إضافة ملف بيان يتضمّن حقل gcm_sender_id، لإتمام اشتراك الإشعارات الفورية. لا يتطلّب سوى Chrome وOpera لأجهزة Android ومتصفّح Samsung استخدام هذه المَعلمة ليتمكّنوا من استخدام FCM أو GCM.
وتستخدِم هذه المتصفحات مَعلمة gcm_sender_id عند اشتراك جهاز أحد المستخدِمين في ميزة "المراسلة عبر السحابة الإلكترونية من Firebase". وهذا يعني أنّه يمكن لخدمة "المراسلة عبر السحابة الإلكترونية من Firebase" التعرّف على جهاز المستخدم والتأكّد من أنّ معرّف المُرسِل يتطابق مع مفتاح واجهة برمجة التطبيقات المقابل وأنّ المستخدم قد منح خادمك الإذن بإرسال رسائل فورية إليه.
في ما يلي ملف بيان بسيط للغاية:
{
"name": "Push Demo",
"short_name": "Push Demo",
"icons": [{
"src": "images/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
}],
"start_url": "/index.html?homescreen=1",
"display": "standalone",
"gcm_sender_id": "<Your Sender ID Here>"
}
عليك ضبط قيمة gcm_sender_id على معرّف المُرسِل من مشروعك على Firebase.
بعد حفظ ملف البيان في مشروعك (manifest.json هو اسم جيد)، يمكنك الإشارة إليه من ملف HTML باستخدام العلامة التالية في عنوان صفحتك.
<link rel="manifest" href="/manifest.json">
في حال عدم إضافة بيان ويب يتضمّن هذه المَعلمات، ستتلقّى استثناءً
عند محاولة اشتراك المستخدم في خدمة إرسال الرسائل الفورية، مع الخطأ
"Registration failed - no sender id provided"
أو "Registration failed -
permission denied"
.
الاشتراك في ميزة "إرسال رسائل من الخادم"
بعد إعداد البيان، يمكنك العودة إلى JavaScript في مواقعك الإلكترونية.
للاشتراك، عليك استدعاء الطريقة subscribe() على عنصر PushManager، الذي يمكنك الوصول إليه من خلال ServiceWorkerRegistration.
سيطلب هذا من المستخدم منح مصدرك الإذن لإرسال إشعارات push. بدون هذا الإذن، لن تتمكّن من إشتراكك بنجاح.
إذا تم حلّ الوعد الذي تم إرجاعه بواسطة الطريقة subscribe()، سيتم منحك عنصر PushSubscription الذي سيحتوي على نقطة نهاية.
يجب حفظ نقطة النهاية على خادمك لكل مستخدم، لأنّك ستحتاج إليها لإرسال رسائل فورية في تاريخ لاحق.
يشترك الرمز التالي للمستخدم في خدمة الرسائل الفورية:
function subscribe() {
// Disable the button so it can't be changed while
// we process the permission request
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = true;
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
serviceWorkerRegistration.pushManager.subscribe()
.then(function(subscription) {
// The subscription was successful
isPushEnabled = true;
pushButton.textContent = 'Disable Push Messages';
pushButton.disabled = false;
// TODO: Send the subscription.endpoint to your server
// and save it to send a push message at a later date
return sendSubscriptionToServer(subscription);
})
.catch(function(e) {
if (Notification.permission === 'denied') {
// The user denied the notification permission which
// means we failed to subscribe and the user will need
// to manually change the notification permission to
// subscribe to push messages
console.warn('Permission for Notifications was denied');
pushButton.disabled = true;
} else {
// A problem occurred with the subscription; common reasons
// include network errors, and lacking gcm_sender_id and/or
// gcm_user_visible_only in the manifest.
console.error('Unable to subscribe to push.', e);
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
}
});
});
}
في هذه المرحلة، يكون تطبيق الويب جاهزًا لتلقّي رسالة فورية، ولكن لن يحدث أي تغيُّر إلى أن نضيف مستمعًا لأحداث الدفع إلى ملف الخدمة العاملة.
أداة معالجة حدث "إرسال المعلومات إلى العميل قبل طلبها من الخادم" في مشغِّل الخدمات
عند تلقّي رسالة دفع (سنتحدث عن كيفية إرسال رسالة دفع في القسم التالي)، سيتم إرسال حدث دفع في الخدمة العاملة، وعند هذه النقطة، ستحتاج إلى عرض إشعار.
self.addEventListener('push', function(event) {
console.log('Received a push message', event);
var title = 'Yay a message.';
var body = 'We have received a push message.';
var icon = '/images/icon-192x192.png';
var tag = 'simple-push-demo-notification-tag';
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
);
});
يسجِّل هذا الرمز أداة مراقبة أحداث الإشعارات الفورية ويعرض إشعارًا يحتوي على عنوان ومقتطف نصي ورمز وعلامة إشعار مُحدَّدَين مسبقًا.
من التفاصيل الدقيقة التي يجب تسليط الضوء عليها في هذا المثال هي طريقة event.waitUntil()
. تتلقّى هذه الطريقة وعدًا وتمدّد مدة معالجة الحدث (أو يمكن اعتبارها عملية إبقاء عامل الخدمة قيد التشغيل) إلى أن يتم حلّ الوعد. في هذه الحالة، الوعد الذي تم تمريره إلى event.waitUntil
هو الوعد الذي تم إرجاعه من showNotification()
.
تعمل علامة الإشعار كمعرّف للإشعارات الفريدة. إذا أرسلنا رسالتَي دفع إلى نقطة نهاية التطبيق نفسها، مع تأخير قصير بينهما، وعرضنا الإشعارات بالعلامة نفسها، سيعرض المتصفّح الإشعار الأول وسيحلّ محلّه الإشعار الثاني عند استلام رسالة الدفع.
إذا كنت تريد عرض إشعارات متعددة في آنٍ واحد، استخدِم علامة مختلفة أو بدون علامة على الإطلاق. سنلقي نظرة على مثال أكثر اكتمالاً لعرض إشعار لاحقًا في هذا المنشور. في الوقت الحالي، لنبسّط الأمور ونرى ما إذا كان إرسال رسالة فورية سيؤدي إلى عرض هذا الإشعار.
إرسال رسالة فورية
لقد اشتركنا في الرسائل الفورية وأصبح عامل الخدمة جاهزًا لعرض إشعار، لذا حان وقت إرسال رسالة فورية من خلال خدمة المراسلة عبر السحابة الإلكترونية Firebase (FCM).
لا ينطبق ذلك إلا على المتصفّحات التي تستخدم إطار عمل Firebase للرسائل.
عند إرسال المتغيّر PushSubscription.endpoint
إلى خادمك، يكون
نقطة النهاية لخدمة المراسلة عبر السحابة الإلكترونية من Firebase خاصة. يحتوي على مَعلمة في نهاية عنوان URL وهي registration_id
.
في ما يلي مثال على نقطة نهاية:
https://fcm.googleapis.com/fcm/send/APA91bHPffi8zclbIBDcToXN_LEpT6iA87pgR-J-MuuVVycM0SmptG-rXdCPKTM5pvKiHk2Ts-ukL1KV8exGOnurOAKdbvH9jcvg8h2gSi-zZJyToiiydjAJW6Fa9mE3_7vsNIgzF28KGspVmLUpMgYLBd1rxaVh-L4NDzD7HyTkhFOfwWiyVdKh__rEt15W9n2o6cZ8nxrP
عنوان URL لخدمة FCM هو:
https://fcm.googleapis.com/fcm/send
سيكون registration_id
على النحو التالي:
APA91bHPffi8zclbIBDcToXN_LEpT6iA87pgR-J-MuuVVycM0SmptG-rXdCPKTM5pvKiHk2Ts-ukL1KV8exGOnurOAKdbvH9jcvg8h2gSi-zZJyToiiydjAJW6Fa9mE3_7vsNIgzF28KGspVmLUpMgYLBd1rxaVh-L4NDzD7HyTkhFOfwWiyVdKh__rEt15W9n2o6cZ8nxrP
ينطبق ذلك على المتصفّحات التي تستخدم "إطار عمل إرسال الرسائل". في المتصفّح العادي، يمكنك ببساطة الحصول على نقطة نهاية ويمكنك الاتصال بنقطة النهاية هذه بطريقة عادية، وسيعمل ذلك بغض النظر عن عنوان URL.
يعني ذلك أنّه عليك التحقّق من أنّ نقطة النهاية هي لخدمة "المراسلة عبر السحابة الإلكترونية من Firebase"، وإذا كانت كذلك، عليك استخراج registration_id. لتنفيذ ذلك في Python، يمكنك إجراء ما يلي:
if endpoint.startswith('https://fcm.googleapis.com/fcm/send'):
endpointParts = endpoint.split('/')
registrationId = endpointParts[len(endpointParts) - 1]
endpoint = 'https://fcm.googleapis.com/fcm/send'
بعد الحصول على معرّف التسجيل، يمكنك إجراء مكالمة إلى واجهة برمجة التطبيقات FCM API. يمكنك الاطّلاع على المستندات المرجعية حول واجهة برمجة التطبيقات للمراسلة عبر السحابة الإلكترونية من Firebase هنا.
في ما يلي الجوانب الأساسية التي يجب تذكُّرها عند استدعاء FCM:
- يجب ضبط عنوان Authorization بقيمة
key=<YOUR_API_KEY>
عند طلب البيانات من واجهة برمجة التطبيقات، حيث يكون<YOUR_API_KEY>
هو مفتاح واجهة برمجة التطبيقات من مشروع Firebase.- تستخدم خدمة "المراسلة عبر السحابة الإلكترونية من Firebase" مفتاح واجهة برمجة التطبيقات للعثور على معرّف المُرسِل المناسب، والتأكّد من أنّه قد منح المستخدم الإذن لمشروعك، وأخيراً، للتأكّد من أنّ عنوان IP الخاص بالخادم مُدرَج في القائمة المسموح بها لهذا المشروع.
- عنوان
Content-Type
مناسب منapplication/json
أوapplication/x-www-form-urlencoded;charset=UTF-8
استنادًا إلى ما إذا كنت تُرسِل البيانات بتنسيق JSON أو بيانات نموذج - صفيف من
registration_ids
: هذه هي أرقام تعريف التسجيل التي تريد استخراجها من نقاط النهاية من المستخدمين.
يُرجى الاطّلاع على المستندات حول كيفية إرسال رسائل فورية من خادمك، ولكن لإجراء فحص سريع لعامل الخدمة، يمكنك استخدام cURL لإرسال رسالة فورية إلى المتصفّح.
استبدِل <YOUR_API_KEY>
و<YOUR_REGISTRATION_ID>
في أمر cURL هذا بقيمتك الخاصة ونفِّذ الأمر من وحدة طرفية.
من المفترض أن يظهر لك إشعار رائع:
curl --header "Authorization: key=<YOUR_API_KEY>" --header
"Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d
"{\"registration_ids\":[\"<YOUR_REGISTRATION_ID>\"]}"
عند تطوير منطق الخلفية، تذكَّر أنّ رأس Authorization وملفه الشخصي تنسيق ملف POST هما خاصان بنقطة نهاية FCM، لذا عليك رصد الحالات التي تكون فيها نقطة النهاية مخصّصة لخدمة FCM وإضافة الرأس وتنسيق ملف POST بشكل مشروط. بالنسبة إلى المتصفحات الأخرى (ونأمل أن يتوفّر Chrome في المستقبل)، ستحتاج إلى تنفيذ بروتوكول Web Push.
من سلبيات التنفيذ الحالي لواجهة برمجة التطبيقات Push API في Chrome هو أنّه لا يمكنك إرسال أي بيانات باستخدام رسالة فورية. لا، لا شيء. ويعود سبب ذلك إلى أنّه في عملية التنفيذ المستقبلية، يجب تشفير بيانات الحمولة على الخادم قبل إرسالها إلى نقطة نهاية الرسائل الفورية. بهذه الطريقة، لن تتمكّن نقطة النهاية، مهما كان مقدّم خدمة الإشعارات الفورية، من عرض محتوى الرسالة بسهولة. ويؤدي ذلك أيضًا إلى الحماية من نقاط الضعف الأخرى، مثل التحقق الضعيف من شهادات HTTPS وهجمات الوسيط بين الخادم وموفّر خدمة الإشعارات الفورية. ومع ذلك، لا يتوفّر هذا التشفير بعد، لذلك في الوقت الحالي، عليك إجراء عملية استرجاع للحصول على المعلومات اللازمة ل заполнения الإشعار.
مثال أكثر اكتمالاً على حدث الإرسال الفوري
الإشعار الذي رأيناه حتى الآن بسيط جدًا، وبالنسبة إلى العيّنات، إنّه ضعيف جدًا في تغطية حالة استخدام في العالم الواقعي.
من الواقعي أنّ معظم المستخدمين سيحتاجون إلى الحصول على بعض المعلومات من الخادم قبل عرض الإشعار. وقد تكون هذه البيانات لتعبئة عنوان التنبيه ورسالته بشيء محدّد، أو يمكنك اتخاذ خطوة إضافية واستخدام ذاكرة التخزين المؤقت لبعض الصفحات أو البيانات لكي يكون كل شيء متاحًا فورًا عند فتح المتصفّح عندما ينقر المستخدم على التنبيه، حتى إذا لم تكن الشبكة متاحة في ذلك الوقت.
في الرمز البرمجي التالي، نحصل على بعض البيانات من واجهة برمجة التطبيقات، ونحوّل الردّ إلى ملف شخصي، ثم نستخدمه لتعبئة الإشعار.
self.addEventListener('push', function(event) {
// Since there is no payload data with the first version
// of push messages, we'll grab some data from
// an API and use it to populate a notification
event.waitUntil(
fetch(SOME_API_ENDPOINT).then(function(response) {
if (response.status !== 200) {
// Either show a message to the user explaining the error
// or enter a generic message and handle the
// onnotificationclick event to direct the user to a web page
console.log('Looks like there was a problem. Status Code: ' + response.status);
throw new Error();
}
// Examine the text in the response
return response.json().then(function(data) {
if (data.error || !data.notification) {
console.error('The API returned an error.', data.error);
throw new Error();
}
var title = data.notification.title;
var message = data.notification.message;
var icon = data.notification.icon;
var notificationTag = data.notification.tag;
return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
});
}).catch(function(err) {
console.error('Unable to retrieve data', err);
var title = 'An error occurred';
var message = 'We were unable to get the information for this push message';
var icon = URL_TO_DEFAULT_ICON;
var notificationTag = 'notification-error';
return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
})
);
});
يُرجى العِلم أنّ event.waitUntil()
يأخذ وعدًا
يؤدي إلى الوعد الذي يعرضه showNotification()
، ما يعني
أنّ مستمع الأحداث لن يخرج إلى أن يكتمل طلب fetch()
غير المتزامن، ويُعرَض
الإشعار.
سيظهر لك إشعار حتى في حال حدوث خطأ. ويعود سبب ذلك إلى أنّ Chrome سيعرض إشعارًا عامًا خاصًا به في حال عدم إجراء ذلك.
فتح عنوان URL عندما ينقر المستخدم على إشعار
عندما ينقر المستخدم على إشعار، يتم إرسال حدث notificationclick
في worker الخدمة. في المعالج، يمكنك اتّخاذ الإجراء المناسب،
مثل التركيز على علامة تبويب أو فتح نافذة تتضمّن عنوان URL معيّنًا:
self.addEventListener('notificationclick', function(event) {
console.log('On notification click: ', event.notification.tag);
// Android doesn't close the notification when you click on it
// See: http://crbug.com/463146
event.notification.close();
// This looks to see if the current is already open and
// focuses if it is
event.waitUntil(
clients.matchAll({
type: "window"
})
.then(function(clientList) {
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
if (client.url == '/' && 'focus' in client)
return client.focus();
}
if (clients.openWindow) {
return clients.openWindow('/');
}
})
);
});
يفتح هذا المثال المتصفّح على جذر مصدر الموقع الإلكتروني، وذلك من خلال التركيز على علامة تبويب حالية من المصدر نفسه في حال توفّرها، وفتح علامة تبويب جديدة في حال عدم توفّرها.
يمكنك الاطّلاع على مشاركة مخصّصة لبعض الإجراءات التي يمكنك تنفيذها باستخدام Notification API.
إلغاء اشتراك جهاز مستخدم
لقد اشتركت في جهاز أحد المستخدمين وتلقّى رسائل فورية، ولكن كيف يمكنك إلغاء اشتراكه؟
إنّ الخطوات الرئيسية المطلوبة لإلغاء اشتراك جهاز المستخدم هي استدعاء الأسلوب
unsubscribe()
على عنصر
PushSubscription
وإزالة نقطة النهاية من خوادمك (لتجنُّب
إرسال رسائل فورية تعلم أنّها لن يتم استلامها). تؤدي التعليمة البرمجية أدناه
هذا الإجراء بالضبط:
function unsubscribe() {
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = true;
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
// To unsubscribe from push messaging, you need get the
// subscription object, which you can call unsubscribe() on.
serviceWorkerRegistration.pushManager.getSubscription().then(
function(pushSubscription) {
// Check we have a subscription to unsubscribe
if (!pushSubscription) {
// No subscription object, so set the state
// to allow the user to subscribe to push
isPushEnabled = false;
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
return;
}
var subscriptionId = pushSubscription.subscriptionId;
// TODO: Make a request to your server to remove
// the subscriptionId from your data store so you
// don't attempt to send them push messages anymore
// We have a subscription, so call unsubscribe on it
pushSubscription.unsubscribe().then(function(successful) {
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
isPushEnabled = false;
}).catch(function(e) {
// We failed to unsubscribe, this can lead to
// an unusual state, so may be best to remove
// the users data from your data store and
// inform the user that you have done so
console.log('Unsubscription error: ', e);
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
});
}).catch(function(e) {
console.error('Error thrown while unsubscribing from push messaging.', e);
});
});
}
إبقاء الاشتراك محدّثًا
قد لا تكون الاشتراكات متزامنة بين "خدمة المراسلة عبر السحابة الإلكترونية من Firebase" وخادمك. تأكَّد من أنّ
خادمك يفكِّر محتوى استجابة طلب POST في واجهة برمجة التطبيقات لـ "المراسلة عبر السحابة الإلكترونية من Firebase"، بحثًا عن نتائج
error:NotRegistered
وcanonical_id
، كما هو موضّح في مستندات "المراسلة عبر السحابة الإلكترونية من Firebase".
قد تتوقف أيضًا مزامنة الاشتراكات بين الخدمة العاملة
وخادمك. على سبيل المثال، بعد الاشتراك أو إلغاء الاشتراك بنجاح، قد يمنعك اتصال الشبكة المضطرب من تعديل الخادم، أو قد يبطل أحد المستخدمين إذن الإشعارات، ما يؤدي إلى إلغاء الاشتراك تلقائيًا. يمكنك التعامل مع
مثل هذه الحالات من خلال التحقّق من نتيجة
serviceWorkerRegistration.pushManager.getSubscription()
بشكل دوري (مثل
عند تحميل الصفحة) ومزامنتها مع الخادم. يمكنك أيضًا
إعادة الاشتراك تلقائيًا إذا لم يعد لديك اشتراك وكانت قيمة Notification.permission == "granted".
في sendSubscriptionToServer()
، عليك التفكير في كيفية التعامل مع
طلبات الشبكة غير الناجحة عند تعديل endpoint
. أحد الحلول هو
تتبُّع حالة endpoint
في ملف تعريف ارتباط
لتحديد ما إذا كان خادمك بحاجة إلى أحدث التفاصيل أم لا.
تؤدي جميع الخطوات أعلاه إلى تنفيذ كامل للرسائل الفورية على الويب في Chrome 46. لا تزال هناك ميزات محدّدة ستسهّل الأمور، (مثل واجهة برمجة تطبيقات عادية لتشغيل الرسائل الفورية)، ولكن يتيح لك هذا الإصدار بدء إنشاء رسائل فورية في تطبيقات الويب اليوم.
كيفية تصحيح أخطاء تطبيق الويب
أثناء تنفيذ رسائل الإشعارات الفورية، ستظهر الأخطاء في أحد المكانَين التاليَين: صفحتك أو الخدمة العاملة.
يمكن تصحيح الأخطاء في الصفحة باستخدام DevTools. لتصحيح أخطاء العامل في الخدمة، لديك خياران:
- انتقِل إلى chrome://inspect > مهام الخدمة. لا يوفّر هذا العرض معلومات كثيرة غير مهام الخدمة التي تعمل حاليًا.
- انتقِل إلى chrome://serviceworker-internals، ويمكنك من هنا الاطّلاع على حالة مهام الخدمة والاطّلاع على الأخطاء، إن توفّرت. هذه الصفحة مؤقتة إلى أن تتوفّر في "أدوات مطوّري البرامج" مجموعة ميزات مشابهة.
من أفضل النصائح التي يمكنني تقديمها لأي مستخدم جديد في مهام الخدمة هي استخدام مربّع الاختيار "فتح نافذة DevTools وإيقاف تنفيذ JavaScript مؤقتًا عند بدء تشغيل مهام الخدمة لتصحيح الأخطاء". سيؤدي وضع علامة في مربّع الاختيار هذا إلى إضافة نقطة توقّف عند بداية الخدمة العاملة وإيقاف التنفيذ مؤقتًا، ما يتيح لك استئناف نص الخدمة العاملة أو التنقّل فيه والتحقّق مما إذا كنت تواجه أي مشاكل.
إذا بدا أنّ هناك مشكلة بين "نظام إرسال الرسائل إلى الأجهزة الجوّالة من Google" وحدث الإرسال في worker الخدمة، ليس هناك الكثير مما يمكنك فعله لتصحيح أخطاء المشكلة لأنّه لا توجد طريقة لتحديد ما إذا كان Chrome قد تلقّى أي شيء. عليك التأكّد من أنّه يتم تلقّي استجابة ناجحة من FCM عندما يُجري خادمك طلبًا إلى واجهة برمجة التطبيقات. سيظهر بالشكل التالي:
{"multicast_id":1234567890,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1234567890"}]}
لاحِظ الردّ "success": 1
. إذا ظهرت لك رسالة خطأ بدلاً من ذلك، يعني ذلك أنّه هناك مشكلة في رقم تعريف تسجيل FCM وأنّه لا يتم إرسال رسالة الدفع إلى Chrome.
تصحيح أخطاء مهام الخدمة على متصفّح Chrome لأجهزة Android
في الوقت الحالي، لا يمكن تصحيح أخطاء خدمات Chrome العاملة في الخلفية على أجهزة Android. عليك الانتقال إلى chrome://inspect، والعثور على جهازك والبحث عن عنصر في القائمة يحمل الاسم "Worker pid:...." والذي يحتوي على عنوان URL لمعالج الخدمة.
تجربة المستخدم في الإشعارات الفورية
يُعدّ فريق Chrome مستندًا يتضمن أفضل الممارسات المتعلّقة بتجربة المستخدم في الإشعارات الفورية، بالإضافة إلى مستند يتناول بعض الحالات القصوى عند التعامل مع الإشعارات الفورية.
- أفضل الممارسات المتعلّقة بتجربة المستخدم في ما يتعلّق بأذونات الإشعارات الفورية
- الحالات الشاذة للإشعارات الفورية والتدابير التي يمكن اتّخاذها للحدّ من حدوثها
مستقبل الرسائل الفورية على Chrome وشبكة الإنترنت المفتوحة
يتناول هذا القسم بعض التفاصيل حول بعض الأجزاء المتعلّقة بمتصفّح Chrome المرتبطة بهذا التنفيذ والتي يجب أن تكون على دراية بها وكيفية اختلافها عن عمليات التنفيذ في المتصفّحات الأخرى.
بروتوكول Web Push ونقاط النهاية
يكمن جمال معيار Push API في أنّه من المفترض أن تتمكّن من أخذ نقطة النهاية ونقلها إلى خادمك وإرسال الرسائل الفورية من خلال تنفيذ Web Push Protocol.
Web Push Protocol هو معيار جديد يمكن لموفّري خدمات الإشعارات الفورية تنفيذه، ويسمح للّمطوّرين بعدم القلق بشأن موفّر خدمات الإشعارات الفورية. والفكرة هي أنّ هذا يتجنّب الحاجة إلى الاشتراك في مفاتيح واجهة برمجة التطبيقات وإرسال بيانات منسَّقة بشكل خاص، كما هو الحال مع FCM.
كان Chrome هو المتصفّح الأول الذي نفَّذ واجهة برمجة التطبيقات Push API، ولا توفّر خدمة "إشعارات Google من خادم الرسائل الفورية" (FCM) gcm_sender_id
، لذلك يتطلّب Chrome استخدام gcm_sender_id
وعليك استخدام واجهة برمجة التطبيقات restful API لخدمة FCM.
والهدف النهائي لمتصفّح Chrome هو الانتقال إلى استخدام Web Push Protocol مع Chrome وFirebase Cloud Messaging.
إلى ذلك الحين، عليك رصد نقطة النهاية "https://fcm.googleapis.com/fcm/send" ومعالجتها بشكل منفصل عن نقاط النهاية الأخرى، أي تنسيق بيانات الحمولة بطريقة معيّنة وإضافة مفتاح التفويض.
How to Implement the Web Push Protocol?
يعمل Firefox Nightly حاليًا على إتاحة ميزة الإشعارات الفورية، ومن المرجّح أن يكون أول متصفّح يطبّق بروتوكول Web Push.
الأسئلة الشائعة
أين يمكنني الاطّلاع على المواصفات؟
https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ https://w3c.github.io/push-api/ https://notifications.spec.whatwg.org/
هل يمكنني منع تلقّي إشعارات مكرّرة إذا كان موقعي الإلكتروني يضمّ مصادر متعدّدة، أو إذا كان لديّ موقع إلكتروني وموقع أصلي؟
لا يتوفّر حلّ لهذه المشكلة في الوقت الحالي، ولكن يمكنك متابعة مستوى التقدّم في Chromium.
السيناريو المثالي هو الحصول على نوع من المعرّفات لجهاز المستخدم ثم مطابقة معرّفات الاشتراك في التطبيق الأصلي وتطبيق الويب من جانب الخادم وتحديد التطبيق الذي سيتم إرسال رسالة فورية إليه. يمكنك إجراء ذلك من خلال حجم الشاشة، ونموذج الجهاز، ومشاركة مفتاح تم إنشاؤه بين تطبيق الويب والتطبيق الأصلي، ولكن لكل نهج إيجابيات وسلبيات.
لماذا أحتاج إلى gcm_sender_id؟
هذا الإجراء مطلوب لكي يتمكّن متصفِّح Chrome وOpera لنظام التشغيل Android ومتصفِّح Samsung من استخدام واجهة برمجة التطبيقات لخدمة "المراسلة عبر السحابة الإلكترونية من Firebase". والهدف هو استخدام Web Push Protocol عندما يتم الانتهاء من وضع المعيار ويمكن أن تتوافق معه خدمة FCM.
لماذا لا يتم استخدام Web Sockets أو الأحداث المُرسَلة من الخادم (EventSource)؟
تتمثل ميزة استخدام الرسائل الفورية في أنّه حتى إذا كانت صفحتك مغلقة، سيتم تنشيط عامل الخدمة وسيكون بإمكانه عرض إشعار. يتم إغلاق اتصال Web Sockets وEventSource عند إغلاق الصفحة أو المتصفّح.
ماذا لو لم أكن بحاجة إلى إرسال الأحداث في الخلفية؟
إذا لم تكن بحاجة إلى إرسال البيانات في الخلفية، فإنّ Web Sockets هي خيار رائع.
متى يمكنني استخدام الإشعارات الفورية بدون عرض إشعارات (أي الإشعارات الفورية الصامتة في الخلفية)؟
لا يتوفّر جدول زمني محدد حتى الآن بشأن توفّر هذه الميزة، ولكن هناك نية لتنفيذ المزامنة في الخلفية، ومع أنّه لم يتم اتخاذ قرار بشأن ذلك أو تحديد مواصفاته، هناك بعض المناقشات حول تفعيل ميزة الدفع الصامت باستخدام المزامنة في الخلفية.
لماذا يتطلّب هذا الإجراء استخدام بروتوكول HTTPS؟ كيف يمكنني حلّ هذه المشكلة أثناء مرحلة التطوير؟
تتطلّب مشغّلو الخدمات مصادر آمنة لضمان أنّ نص مشغّل الخدمة يأتي من المصدر المقصود ولم يتم إنشاؤه من خلال هجوم من نوع "الرجل في المنتصف" . ويعني ذلك حاليًا استخدام HTTPS على المواقع الإلكترونية المنشورة، على الرغم من أنّ localhost سيعمل أثناء التطوير.
كيف يبدو توافق المتصفّح؟
يتيح Chrome هذه الميزة في إصداره الثابت، وتعمل Mozilla على طرحها في الإصدار Firefox Nightly. اطّلِع على الخطأ implementing the Push API للحصول على مزيد من المعلومات، ويمكنك تتبُّع عملية تنفيذ الإشعارات هنا.
هل يمكنني إزالة إشعار بعد فترة زمنية معيّنة؟
لا يمكن حاليًا الحصول على هذه القائمة، ولكننا نخطّط لإتاحة ذلك. إذا كان لديك حالة استخدام لضبط مهلة انتهاء صلاحية للإشعار بعد عرضه، يُرجى إعلامنا بها. لإضافة تعليق، يُرجى النقر على "إضافة تعليق"، وسنعيد توجيهه إلى فريق Chrome.
إذا كنت بحاجة فقط إلى إيقاف إرسال إشعار فوري إلى المستخدم بعد فترة زمنية معيّنة، ولا يهمّك مدة بقاء الإشعار مرئيًا، يمكنك استخدام مَعلمة وقت انتهاء الصلاحية (ttl) في "المراسلة عبر السحابة الإلكترونية من Firebase"، مزيد من المعلومات هنا.
ما هي قيود الرسائل الفورية في Chrome؟
هناك بعض القيود الموضّحة في هذه المشاركة:
- يؤدي استخدام Chrome لخدمة CCM كخدمة دفع إلى فرض عدد من متطلبات الملكية الخاصة. نحن نعمل معًا لمعرفة ما إذا كان بإمكاننا رفع بعض هذه القيود في المستقبل.
- يجب عرض إشعار عند تلقّي رسالة فورية.
- يُرجى العِلم أنّه في حال عدم تشغيل متصفّح Chrome على الكمبيوتر المكتبي، لن يتم تلقّي الرسائل الفورية. يختلف ذلك عن نظامَي التشغيل ChromeOS وAndroid حيث سيتم تلقّي رسائل الإشعارات push دائمًا.
هل يجب استخدام Permissions API؟
تم تنفيذ واجهة برمجة التطبيقات Permission API في Chrome، ولكنّها لن تكون متاحة بالضرورة في جميع المتصفّحات. مزيد من المعلومات
لماذا لا يفتح Chrome علامة التبويب السابقة عند النقر على إشعار؟
ولا تؤثر هذه المشكلة إلا في الصفحات التي لا يتحكم فيها مشغّل خدمات حاليًا. يمكنك الاطّلاع على المزيد من المعلومات هنا.
ماذا لو كان الإشعار قديمًا في الوقت الذي تلقّى فيه جهاز المستخدم الإشعار الفوري؟
يجب دائمًا عرض إشعار عند تلقّي رسالة فورية. في السيناريو الذي تريد فيه إرسال إشعار ولكنّه يكون مفيدًا فقط لمدة زمنية معيّنة، يمكنك استخدام المَعلمة time_to_live في CCM كي لا تُرسِل خدمة "المراسلة عبر السحابة الإلكترونية من Firebase" رسالة الإشعار الفوري إذا تجاوزت وقت انتهاء الصلاحية.
يمكنك الاطّلاع على مزيد من التفاصيل هنا.
ماذا يحدث إذا أرسلتُ 10 رسائل دفع ولكن أريد أن يتلقّى الجهاز رسالة واحدة فقط؟
تحتوي واجهة برمجة التطبيقات للمراسلة عبر السحابة الإلكترونية من Firebase على مَعلمة collapse_key يمكنك استخدامها لإعلام واجهة برمجة التطبيقات للمراسلة عبر السحابة الإلكترونية من Firebase باستبدال أي رسالة معلّقة تحتوي على مَعلمة collapse_key نفسها بالرسالة الجديدة.