Push Notifications در Open Web

اگر از اتاقی از توسعه‌دهندگان بپرسید که چه ویژگی‌های دستگاه تلفن همراه در وب وجود ندارد، اعلان‌های فشاری همیشه در لیست بالا هستند.

اعلان‌های فشاری به کاربران شما این امکان را می‌دهد که به‌روزرسانی‌های به‌موقع سایت‌هایی را که دوست دارند انتخاب کنند و به شما این امکان را می‌دهند که دوباره آنها را با محتوای سفارشی‌سازی‌شده و جذاب جذب کنید.

از نسخه 42 کروم، Push API و Notification API برای توسعه دهندگان در دسترس است.

Push API در کروم به چند تکه فناوری مختلف متکی است، از جمله مانیفست‌های برنامه‌های وب و کارکنان خدمات . در این پست ما به هر یک از این فناوری‌ها نگاه می‌کنیم، اما تنها حداقل آن برای راه‌اندازی و اجرای پیام‌های فشاری. برای درک بهتر برخی از ویژگی‌های دیگر مانیفست‌ها و قابلیت‌های آفلاین کارکنان خدمات، لطفاً پیوندهای بالا را بررسی کنید.

همچنین به مواردی که در نسخه‌های بعدی کروم به API اضافه می‌شود نگاه می‌کنیم و در نهایت یک پرسش متداول خواهیم داشت.

پیاده سازی Push Messaging برای کروم

این بخش هر مرحله ای را که باید برای پشتیبانی از پیام رسانی فشاری در برنامه وب خود تکمیل کنید، توضیح می دهد.

ثبت نام کارگر خدماتی

وابستگی داشتن یک سرویس دهنده برای پیاده سازی پیام های فشار برای وب وجود دارد. دلیل این امر این است که وقتی یک پیام فشار دریافت می‌شود، مرورگر می‌تواند یک سرویس‌کار را راه‌اندازی کند که در پس‌زمینه بدون باز شدن صفحه اجرا می‌شود و یک رویداد را ارسال می‌کند تا بتوانید تصمیم بگیرید که چگونه آن پیام فشار را مدیریت کنید.

در زیر نمونه ای از نحوه ثبت یک سرویس دهنده در برنامه وب خود آورده شده است. هنگامی که ثبت نام با موفقیت به پایان رسید ، ابتدا () را فراخوانی می کنیم که به زودی به آن خواهیم پرداخت.

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 که منطق مدیریت یک پیام فشار را دارد، بررسی می‌کنیم که سرویس‌کاران پشتیبانی می‌شوند. در اینجا ما به سادگی به مرورگر می گوییم که این فایل جاوا اسکریپت سرویس دهنده سایت ما است.

حالت اولیه را تنظیم کنید

نمونه‌ای از UX پیام‌رسان فشار فعال و غیرفعال در کروم.

پس از ثبت نام سرویس‌کار، باید وضعیت رابط کاربری خود را تنظیم کنیم.

کاربران انتظار دارند که یک رابط کاربری ساده برای فعال یا غیرفعال کردن پیام‌های فشاری برای سایت شما، و انتظار دارند که هر تغییری که رخ می‌دهد به‌روز باشد. به عبارت دیگر، اگر آنها پیام‌های فشاری را برای سایت شما فعال می‌کنند، آن را ترک می‌کنند و یک هفته بعد برمی‌گردند، رابط کاربری شما باید مشخص کند که پیام‌های فشار قبلاً فعال شده‌اند.

شما می توانید برخی از دستورالعمل های UX را در این سند بیابید، در این مقاله ما بر جنبه های فنی تمرکز خواهیم کرد.

در این مرحله ممکن است فکر کنید فقط دو حالت وجود دارد، فعال یا غیرفعال. با این حال، وضعیت‌های دیگری پیرامون اعلان‌ها وجود دارد که باید آنها را در نظر بگیرید.

نموداری که ملاحظات مختلف و وضعیت فشار در کروم را برجسته می کند

تعدادی API وجود دارد که باید قبل از فعال کردن دکمه خود بررسی کنیم، و اگر همه چیز پشتیبانی می‌شود، می‌توانیم رابط کاربری خود را فعال کرده و وضعیت اولیه را طوری تنظیم کنیم که نشان دهد پیام‌های فشاری مشترک است یا خیر.

از آنجایی که اکثر این بررسی ها منجر به غیرفعال شدن رابط کاربری ما می شود، باید حالت اولیه را روی غیرفعال تنظیم کنید. همچنین اگر مشکلی در جاوا اسکریپت صفحه شما وجود داشته باشد، به عنوان مثال فایل JS قابل دانلود نیست یا کاربر جاوا اسکریپت را غیرفعال کرده است، از هرگونه سردرگمی جلوگیری می کند.

<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 راه‌اندازی کنیم و برخی پارامترها را به مانیفست خود اضافه کنیم تا از Firebase Cloud Messaging (FCM) استفاده کنیم. به عنوان Google Cloud Messaging (GCM).

یک پروژه در کنسول برنامه نویس Firebase بسازید

Chrome از FCM برای مدیریت ارسال و تحویل پیام‌های فشار استفاده می‌کند. با این حال، برای استفاده از FCM API، باید یک پروژه در کنسول توسعه دهنده Firebase راه اندازی کنید.

مراحل زیر مختص کروم، اپرا برای اندروید و مرورگر سامسونگ است که از FCM استفاده می کنند. در ادامه مقاله در مورد نحوه عملکرد این کار در سایر مرورگرها بحث خواهیم کرد.

یک پروژه توسعه دهنده Firebase جدید ایجاد کنید

برای شروع باید یک پروژه جدید در https://console.firebase.google.com/ با کلیک بر روی «ایجاد پروژه جدید» ایجاد کنید.

اسکرین شات پروژه جدید Firebase

یک نام پروژه اضافه کنید، پروژه را ایجاد کنید و به داشبورد پروژه هدایت خواهید شد:

خانه پروژه Firebase

از این داشبورد، روی چرخ دنده کنار نام پروژه خود در گوشه بالا سمت چپ کلیک کنید و روی «تنظیمات پروژه» کلیک کنید.

منوی تنظیمات پروژه Firebase

در صفحه تنظیمات، روی تب 'Cloud Messaging' کلیک کنید.

منوی پیام‌رسانی ابری پروژه Firebase

این صفحه حاوی کلید API برای پیام‌رسانی فشاری است که بعداً از آن استفاده خواهیم کرد و شناسه فرستنده که باید در مانیفست برنامه وب در بخش بعدی قرار دهیم.

یک مانیفست برنامه وب اضافه کنید

برای push، باید یک فایل مانیفست با فیلد gcm_sender_id اضافه کنیم تا اشتراک push موفق شود. این پارامتر فقط توسط Chrome، Opera for Android و Samsung Browser مورد نیاز است تا بتوانند از FCM / GCM استفاده کنند.

gcm_sender_id توسط این مرورگرها هنگامی که یک دستگاه کاربر را با FCM مشترک می کند استفاده می شود. این بدان معنی است که FCM می تواند دستگاه کاربر را شناسایی کند و مطمئن شود که شناسه فرستنده شما با کلید API مربوطه مطابقت دارد و کاربر به سرور شما اجازه داده است که برای آنها پیام های فشار ارسال کند.

در زیر یک فایل مانیفست فوق العاده ساده وجود دارد:

{
    "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" استثنا خواهید داشت.

در Push Messaging مشترک شوید

اکنون که یک مانیفست تنظیم کرده اید، می توانید به جاوا اسکریپت سایت خود بازگردید.

برای اشتراک، باید متد subscribe() را در شی PushManager فراخوانی کنید، که از طریق ServiceWorkerRegistration به آن دسترسی دارید.

با این کار از کاربر می‌خواهد که به منبع شما اجازه ارسال اعلان‌های فشاری بدهد. بدون این مجوز، نمی توانید با موفقیت مشترک شوید.

اگر وعده بازگشتی توسط متد 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';
        }
        });
    });
}

در این مرحله برنامه وب شما برای دریافت پیام فشار آماده است، اگرچه تا زمانی که شنونده رویداد push را به فایل سرویس کار خود اضافه نکنیم، هیچ اتفاقی نخواهد افتاد.

شنونده رویداد Push Worker Service

هنگامی که یک پیام فشار دریافت می شود (ما در مورد نحوه ارسال پیام فشار در بخش بعدی صحبت خواهیم کرد)، یک رویداد فشار در سرویس دهنده شما ارسال می شود، در این مرحله باید یک اعلان نمایش دهید.

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 ارسال می شود Promise برگشتی از showNotification() .

تگ اعلان به عنوان یک شناسه برای اعلان های منحصر به فرد عمل می کند. اگر دو پیغام فشار را به یک نقطه پایانی با یک تاخیر کوتاه بین آنها ارسال کنیم و اعلان‌ها را با همان برچسب نمایش دهیم، مرورگر اولین اعلان را نمایش می‌دهد و با دریافت پیام فشار، اعلان دوم را جایگزین آن می‌کند.

اگر می خواهید چندین اعلان را به طور همزمان نشان دهید، از یک برچسب متفاوت یا بدون برچسب استفاده کنید. در ادامه این پست به نمونه کامل‌تری از نمایش اعلان نگاه خواهیم کرد. در حال حاضر، اجازه دهید همه چیز را ساده نگه داریم و ببینیم آیا ارسال یک پیام فشار این اعلان را نشان می دهد یا خیر.

ارسال یک پیام فشاری

ما در پیام‌های فشار مشترک شده‌ایم و کارمند خدمات ما آماده است تا یک اعلان را نشان دهد، بنابراین زمان ارسال پیام فشار از طریق FCM فرا رسیده است.

این فقط برای مرورگرهایی که از FCM استفاده می کنند قابل اجرا است.

هنگامی که متغیر PushSubscription.endpoint را به سرور خود ارسال می کنید، نقطه پایانی FCM ویژه است. این یک پارامتر در انتهای URL دارد که یک registration_id است.

یک مثال پایانی این خواهد بود:

https://fcm.googleapis.com/fcm/send/APA91bHPffi8zclbIBDcToXN_LEpT6iA87pgR-J-MuuVVycM0SmptG-rXdCPKTM5pvKiHk2Ts-ukL1KV8exGOnurOAKdbvH9jcvg8h2gSi-zZJyToiiydjAJW6Fa9mE3_7vsNIgzF28KGspVmLUpMgYLBd1rxaVh-L4NDzD7HyTkhFOfwWiyVdKh__rEt15W9n2o6cZ8nxrP

آدرس FCM این است:

https://fcm.googleapis.com/fcm/send

registration_id خواهد بود:

APA91bHPffi8zclbIBDcToXN_LEpT6iA87pgR-J-MuuVVycM0SmptG-rXdCPKTM5pvKiHk2Ts-ukL1KV8exGOnurOAKdbvH9jcvg8h2gSi-zZJyToiiydjAJW6Fa9mE3_7vsNIgzF28KGspVmLUpMgYLBd1rxaVh-L4NDzD7HyTkhFOfwWiyVdKh__rEt15W9n2o6cZ8nxrP

این مخصوص مرورگرهایی است که از FCM استفاده می کنند. در یک مرورگر معمولی شما به سادگی یک نقطه پایانی دریافت می کنید و آن نقطه پایانی را به روشی استاندارد فراخوانی می کنید و بدون توجه به URL کار می کند.

این به این معنی است که در سرور خود باید بررسی کنید که آیا نقطه پایانی مربوط به FCM است یا خیر، ثبت_id را استخراج کنید. برای انجام این کار در پایتون می توانید کارهایی مانند زیر انجام دهید:

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 تماس بگیرید. می توانید اسناد مرجع را در FCM API در اینجا بیابید.

نکات کلیدی که هنگام تماس با FCM باید به خاطر بسپارید عبارتند از:

  • یک عنوان مجوز با مقدار key=&lt;YOUR_API_KEY&gt; باید هنگام تماس با API تنظیم شود، جایی که &lt;YOUR_API_KEY&gt; کلید API پروژه Firebase است.
    • کلید API توسط FCM برای یافتن شناسه فرستنده مناسب استفاده می شود، اطمینان حاصل شود که کاربر مجوز پروژه شما را داده است و در نهایت اطمینان حاصل می کند که آدرس IP سرور برای آن پروژه در لیست مجاز قرار دارد.
  • یک هدر Content-Type مناسب برای application/json یا application/x-www-form-urlencoded;charset=UTF-8 بسته به اینکه داده ها را به صورت JSON یا فرم ارسال کنید.
  • آرایه‌ای از registration_ids - اینها شناسه‌های ثبت نام هستند که از نقاط پایانی کاربران خود استخراج می‌کنید.

لطفاً اسناد مربوط به نحوه ارسال پیام های فشاری از سرور خود را بررسی کنید ، اما برای بررسی سریع کارمند خدمات خود می توانید از cURL برای ارسال پیام فشار به مرورگر خود استفاده کنید.

&lt;YOUR_API_KEY&gt; و &lt;YOUR_REGISTRATION_ID&gt; در این دستور 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>\"]}"
نمونه ای از پیام فشار از Chrome برای Android.

هنگام توسعه منطق باطن خود، به یاد داشته باشید که هدر و فرمت Authorization بدنه POST مختص نقطه پایانی FCM است، بنابراین تشخیص دهید که نقطه پایانی برای FCM است و به صورت مشروط هدر را اضافه کنید و بدنه POST را قالب بندی کنید. برای سایر مرورگرها (و امیدواریم Chrome در آینده) باید پروتکل Web Push را پیاده سازی کنید.

نقطه ضعف اجرای فعلی Push API در کروم این است که نمی توانید هیچ داده ای را با یک پیام فشار ارسال کنید. نه هیچی دلیل این امر این است که در اجرای آینده، داده‌های payload قبل از ارسال به یک نقطه پایانی پیام‌رسان فشاری باید روی سرور شما رمزگذاری شوند. به این ترتیب نقطه پایانی، هر ارائه دهنده فشاری که باشد، نمی تواند محتوای پیام فشار را به راحتی مشاهده کند. این همچنین در برابر آسیب‌پذیری‌های دیگر مانند اعتبار سنجی ضعیف گواهی‌های HTTPS و حملات انسان در وسط بین سرور شما و ارائه‌دهنده فشار محافظت می‌کند. با این حال، این رمزگذاری هنوز پشتیبانی نمی‌شود، بنابراین در این مدت باید برای دریافت اطلاعات مورد نیاز برای تکمیل یک اعلان، واکشی انجام دهید.

یک مثال کامل تر Push Event

اعلانی که تاکنون دیده‌ایم بسیار ابتدایی است و تا آنجا که نمونه‌ها پیش می‌روند، در پوشش یک مورد استفاده در دنیای واقعی بسیار ضعیف است.

در واقع، اکثر مردم می خواهند قبل از نمایش اعلان، اطلاعاتی را از سرور خود دریافت کنند. این ممکن است داده‌ای برای پر کردن عنوان و پیام اعلان با چیزی خاص باشد، یا یک قدم فراتر رفته و برخی از صفحات یا داده‌ها را در حافظه پنهان نگه می‌دارد تا زمانی که کاربر روی اعلان کلیک می‌کند، همه چیز بلافاصله پس از باز شدن مرورگر در دسترس باشد - حتی اگر شبکه در آن زمان در دسترس نیست

در کد زیر مقداری داده را از یک API واکشی می کنیم، پاسخ را به یک شی تبدیل می کنیم و از آن برای پر کردن اعلان خود استفاده می کنیم.

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 در سرویس کار شما ارسال می شود. در کنترلر خود، می‌توانید اقدامات مناسب را انجام دهید، مانند فوکوس کردن یک برگه یا باز کردن یک پنجره با یک 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('/');
        }
    })
    );
});

این مثال مرورگر را به ریشه اصلی سایت باز می کند، با تمرکز بر یک برگه با همان مبدا موجود در صورت وجود، و در غیر این صورت باز کردن یک برگه جدید.

در اینجا یک پست اختصاص داده شده است به برخی از کارهایی که می توانید با اعلان 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);
        });
    });
}

به روز نگه داشتن اشتراک

اشتراک ها ممکن است بین FCM و سرور شما هماهنگ نباشد. اطمینان حاصل کنید که سرور شما بدنه پاسخ ارسال POST FCM API را تجزیه می کند error:NotRegistered همانطور که در مستندات FCM توضیح داده شده canonical_id .

همچنین ممکن است اشتراک‌ها بین کارمند سرویس و سرور شما هماهنگ نباشد. به عنوان مثال، پس از اشتراک/لغو با موفقیت، اتصال شبکه ضعیف ممکن است مانع از به‌روزرسانی سرورتان شود. یا ممکن است کاربر مجوز اعلان‌ها را لغو کند، که باعث لغو اشتراک خودکار می‌شود. با بررسی نتایج serviceWorkerRegistration.pushManager.getSubscription() به صورت دوره ای (مثلاً در بارگذاری صفحه) و همگام سازی آن با سرور، چنین مواردی را مدیریت کنید. همچنین اگر دیگر اشتراک ندارید، ممکن است بخواهید دوباره به طور خودکار مشترک شوید و Notification.permission == 'اعطا شده'.

در sendSubscriptionToServer() باید در نظر بگیرید که چگونه درخواست های شبکه ناموفق را هنگام به روز رسانی endpoint مدیریت می کنید. یک راه حل این است که وضعیت endpoint را در یک کوکی ردیابی کنید تا مشخص شود آیا سرور شما به آخرین جزئیات نیاز دارد یا خیر.

تمام مراحل بالا منجر به اجرای کامل پیام‌رسانی فشاری در وب در Chrome 46 می‌شود. هنوز ویژگی‌های مشخصی وجود دارد که کار را آسان‌تر می‌کند (مانند یک API استاندارد برای راه‌اندازی پیام‌های فشار)، اما این نسخه به شما امکان می‌دهد شروع کنید. ایجاد پیام‌رسانی فشاری در برنامه‌های وب شما.

چگونه برنامه وب خود را اشکال زدایی کنیم

هنگام پیاده سازی پیام های فشار، اشکالات در یکی از دو مکان وجود دارند: صفحه شما یا کارمند خدمات شما.

اشکالات صفحه را می توان با استفاده از DevTools رفع اشکال کرد. برای اشکال زدایی مشکلات مربوط به سرویس کارگر، دو گزینه دارید:

  1. به chrome://inspect > Service Workers بروید. این نما اطلاعات زیادی به جز کارگران خدماتی که در حال حاضر در حال اجرا هستند ارائه نمی دهد.
  2. به chrome://serviceworker-internals بروید و از اینجا می توانید وضعیت سرویسکاران را مشاهده کنید و در صورت وجود خطاها را مشاهده کنید. این صفحه تا زمانی که DevTools مجموعه ای از ویژگی های مشابه را نداشته باشد موقت است.

یکی از بهترین راهنمایی‌هایی که می‌توانم به هر کسی که تازه وارد سرویس‌دهی می‌شود، ارائه کنم، استفاده از چک باکس به نام «باز کردن پنجره DevTools و توقف اجرای جاوا اسکریپت در راه‌اندازی سرویس‌کار برای اشکال‌زدایی» است. این چک باکس یک نقطه انفصال در شروع سرویس‌کار شما اضافه می‌کند و اجرای آن را متوقف می‌کند ، این به شما امکان می‌دهد اسکریپت سرویس‌کارگر خود را از سر بگیرید یا قدم بزنید و ببینید آیا با مشکلی مواجه شدید.

اسکرین شات نشان می‌دهد که چک باکس اجرای مکث در سرویس‌کار-داخلی‌ها کجاست.

اگر به نظر می‌رسد بین FCM و رویداد فشار سرویس‌دهنده‌تان مشکلی وجود دارد، نمی‌توانید کار زیادی برای رفع اشکال انجام دهید زیرا هیچ راهی برای مشاهده اینکه آیا Chrome چیزی دریافت کرده است یا خیر وجود ندارد. نکته کلیدی که باید اطمینان حاصل کرد این است که وقتی سرور شما یک تماس API برقرار می کند، پاسخ FCM موفقیت آمیز است. چیزی شبیه به این خواهد بود:

{"multicast_id":1234567890,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1234567890"}]}

به "success": 1 پاسخ. اگر به جای آن مشکلی مشاهده کردید، نشان می‌دهد که چیزی در شناسه ثبت FCM درست نیست و پیام فشار به Chrome ارسال نمی‌شود.

اشکال زدایی کارگران سرویس در کروم برای اندروید

در حال حاضر اشکال زدایی کارگران سرویس در Chrome for Android واضح نیست. باید به chrome://inspect بروید، دستگاه خود را پیدا کنید و به دنبال موردی از فهرست با نام «Worker pid:...» بگردید که نشانی اینترنتی کارمند خدمات شما را دارد.

عکس صفحه نمایش محل زندگی کارکنان خدمات در Chrome را بازرسی می کنند

UX برای Push Notifications

تیم کروم سندی از بهترین روش‌ها برای UX اعلان‌های فشاری و همچنین سندی که برخی از موارد لبه هنگام کار با اعلان‌های فشاری را پوشش می‌دهد، گردآوری کرده است.

آینده پیام‌رسانی فشاری در کروم و وب باز

این بخش به جزئیات کمی پیرامون برخی از بخش های خاص Chrome این پیاده سازی می پردازد که باید از آنها آگاه باشید و تفاوت آن با سایر پیاده سازی های مرورگر چیست.

پروتکل فشار وب و نقاط پایانی

زیبایی استاندارد Push API این است که شما باید بتوانید با اجرای پروتکل Web Push، نقطه پایانی را بگیرید، آنها را به سرور خود منتقل کنید و پیام های فشار ارسال کنید.

پروتکل Web Push استاندارد جدیدی است که ارائه دهندگان فشار می توانند آن را پیاده سازی کنند و به توسعه دهندگان این امکان را می دهد که نگران نباشند ارائه دهنده فشار کیست. ایده این است که با این کار نیازی به ثبت نام برای کلیدهای API و ارسال داده‌های فرمت‌بندی‌شده خاص، مانند آنچه در FCM وجود دارد، نمی‌شود.

Chrome اولین مرورگری بود که Push API را پیاده سازی کرد و FCM از پروتکل Web Push پشتیبانی نمی کند، به همین دلیل است که Chrome به gcm_sender_id نیاز دارد و شما باید از API استراحت برای FCM استفاده کنید.

هدف نهایی کروم حرکت به سمت استفاده از پروتکل فشار وب با کروم و FCM است.

تا آن زمان، باید نقطه پایانی "https://fcm.googleapis.com/fcm/send" را شناسایی کنید و آن را جدا از سایر نقاط پایانی مدیریت کنید، یعنی داده های بارگذاری را به روشی خاص قالب بندی کنید و کلید Authorization را اضافه کنید.

چگونه پروتکل Web Push را پیاده سازی کنیم؟

Firefox Nightly در حال حاضر روی push کار می کند و احتمالاً اولین مرورگری خواهد بود که پروتکل 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 for Android و مرورگر سامسونگ بتوانند از Firebase Cloud Messaging (FCM) API استفاده کنند. هدف استفاده از پروتکل Web Push زمانی است که استاندارد نهایی شد و FCM بتواند از آن پشتیبانی کند.

چرا از سوکت های وب یا رویدادهای ارسال شده توسط سرور (EventSource) استفاده نمی کنید؟

مزیت استفاده از پیام های فشاری این است که حتی اگر صفحه شما بسته شود، سرویس دهنده شما از خواب بیدار می شود و می تواند یک اعلان را نشان دهد. هنگامی که صفحه یا مرورگر بسته می شود اتصال Web Sockets و EventSource بسته می شود.

اگر به تحویل رویداد پس‌زمینه نیاز نداشته باشم، چه؟

اگر به تحویل پس‌زمینه نیاز ندارید، سوکت‌های وب یک گزینه عالی هستند.

چه زمانی می توانم بدون نمایش اعلان ها (یعنی فشار پس زمینه بی صدا) از فشار استفاده کنم؟

هنوز هیچ جدول زمانی برای اینکه چه زمانی در دسترس خواهد بود وجود ندارد، اما قصد داریم همگام‌سازی پس‌زمینه را پیاده‌سازی کنیم و در حالی که تصمیم‌گیری نشده است یا مشخص نیست، بحث در مورد فعال کردن فشار بی‌صدا با همگام‌سازی پس‌زمینه وجود دارد.

چرا این به HTTPS نیاز دارد؟ چگونه می توانم در طول توسعه روی این موضوع کار کنم؟

کارکنان سرویس برای اطمینان از اینکه اسکریپت کارگر سرویس از مبدأ مورد نظر است و از یک حمله مرد میانی به وجود نیامده است، به منابع امن نیاز دارند. در حال حاضر، این به معنای استفاده از HTTPS در سایت‌های زنده است، اگرچه لوکال هاست در طول توسعه کار خواهد کرد.

پشتیبانی مرورگر چگونه به نظر می رسد؟

کروم در نسخه پایدار خود پشتیبانی می‌کند و موزیلا روی فایرفاکس نایتلی کار می‌کند. برای اطلاعات بیشتر به اجرای اشکال Push API مراجعه کنید و می‌توانید اجرای Notification آنها را در اینجا دنبال کنید.

آیا می توانم یک اعلان را بعد از یک دوره زمانی مشخص حذف کنم؟

در حال حاضر این امکان پذیر نیست، اما ما در حال برنامه ریزی برای اضافه کردن پشتیبانی برای دریافت لیستی از اعلان های قابل مشاهده در حال حاضر هستیم. اگر یک مورد استفاده برای تنظیم انقضا برای اعلان پس از نمایش داده ایجاد شده دارید، مایلیم بدانیم آن چیست، بنابراین لطفاً نظری را اضافه کنید و ما آن را به تیم Chrome بازگردانیم.

اگر فقط باید پس از یک دوره زمانی مشخص، ارسال اعلان فشاری به کاربر را متوقف کنید، و اهمیتی نمی‌دهید که اعلان تا چه مدت قابل مشاهده است، می‌توانید از پارامتر time to live (ttl) FCM استفاده کنید، اینجا بیشتر بدانید .

محدودیت‌های ارسال پیام فشاری در کروم چیست؟

در این پست چند محدودیت وجود دارد:

  • استفاده کروم از CCM به عنوان یک سرویس فشار، تعدادی از الزامات اختصاصی را ایجاد می کند. ما با هم کار می کنیم تا ببینیم آیا می توان برخی از این موارد را در آینده برداشت.
  • هنگام دریافت پیام فشار، باید یک اعلان نشان دهید.
  • کروم روی دسک‌تاپ این هشدار را دارد که اگر کروم در حال اجرا نباشد، پیام‌های فشاری دریافت نمی‌شوند. این با ChromeOS و Android که در آن پیام‌های فشار همیشه دریافت می‌شوند متفاوت است.

آیا نباید از Permissions API استفاده کنیم؟

Permission API در کروم پیاده سازی شده است، اما لزوماً در همه مرورگرها در دسترس نیست. در اینجا می توانید اطلاعات بیشتری کسب کنید .

چرا وقتی روی اعلان کلیک می‌کنم، کروم برگه قبلی را باز نمی‌کند؟

این مشکل فقط صفحاتی را تحت تأثیر قرار می دهد که در حال حاضر توسط یک سرویس دهنده کنترل نمی شوند. در اینجا می توانید اطلاعات بیشتری کسب کنید .

اگر تا زمانی که دستگاه کاربر فشار را دریافت کرد، یک اعلان قدیمی باشد، چه؟

همیشه باید هنگام دریافت پیام فشار، یک اعلان نشان دهید. در سناریویی که می‌خواهید اعلان ارسال کنید اما فقط برای مدت زمان مشخصی مفید است، می‌توانید از پارامتر "time_to_live" در CCM استفاده کنید تا در صورت سپری شدن زمان انقضا، FCM پیام فشار ارسال نکند.

جزئیات بیشتر را می توان در اینجا یافت .

اگر من 10 پیام فشار ارسال کنم اما بخواهم دستگاه فقط یک پیام دریافت کند چه اتفاقی می افتد؟

FCM دارای یک پارامتر «collapse_key» است که می‌توانید از آن استفاده کنید تا به FCM بگویید هر پیام معلقی را که همان «collapse_key» را دارد، با پیام جدید جایگزین کند.

جزئیات بیشتر را می توان در اینجا یافت .