Push Notifications
Push-notifikaatiot voivat saavuttaa käyttäjät jopa silloin, kun sovellus ei ole auki. Selain tilaa kerran, sovellus tallentaa tilauksen, ja palvelin käyttää sitä lähettääkseen ilmoituksia, kun tapahtuma occurs. Push hallitsee tilausten tekemistä ja peruuttamista selainympäristössä. Palvelimella PushSender lähettää PushMessage:in tallennettuun tilaukseen.
Asennus ja edellytykset
Push-notifikaatiot tarjoavat erillinen moduuli. Lisää se sovellukseesi:
- Maven
- Gradle
<dependency>
<groupId>com.webforj</groupId>
<artifactId>webforj-push</artifactId>
</dependency>
dependencies {
implementation 'com.webforj:webforj-push'
}
Push-notifikaatiot vaativat:
- Servletin käyttöönoton, kuten Jetty, Spring Boot tai WAR-tiedosto.
- Avaintparin, joka luodaan alla ja jota käyttöönotto käyttää allekirjoittaakseen ilmoituksia.
- Suojatun alkuperän. Selaimet hylkäävät tilaukset, joita toimitetaan muulla kuin
https:llä, paitsilocalhost-osoitteesta kehityksen aikana.
Lisätietoja suojatuista konteksteista ja siitä, miksi ne ovat tärkeitä, katso Suojatut kontekstit MDN -dokumentaatiossa.
Avainten luominen
Push-palvelut hyväksyvät vain ilmoituksia, jotka on allekirjoitettu käyttöönoton toimesta, johon selain on tilannut. Suorita rakennusliitännäinen kerran jokaiselle käyttöönotolle luodaksesi sen avaintparin:
- Maven
- Gradle
mvn webforj:push-keys
./gradlew webforjPushKeys
Komento tulostaa kolme konfiguraatioriviä. Liitä ne application.properties-tiedostoon ilman lainausmerkkejä tai kopioi ne sellaisina kuin ne on tulostettu webforj.conf-tiedostoon. Korvaa aihealue käyttöönoton yhteystiedolla. Sen on oltava mailto: tai https://-osoite, jota push-palvelut voivat käyttää ottamaan yhteyttä operaattoriin.
webforj.push.public-key=...
webforj.push.private-key=...
webforj.push.subject=mailto:ops@example.com
| Ominaisuus | Selitys |
|---|---|
webforj.push.public-key | Julkinen puolisko avaintparista, jota käyttöönotto käyttää ilmoitusten allekirjoittamiseen |
webforj.push.private-key | Yksityinen puolisko avaintparista. Kuten kaikki muut salaisuudet, pidä se poissa lähdekoodinhallinnasta |
webforj.push.subject | Käyttöönoton yhteystieto. Sen on oltava mailto: tai https://-osoite, jota push-palvelut voivat käyttää ottaakseen yhteyttä operaattoriin |
Sovellus lukee nämä ominaisuudet käynnistyksessä. Jos konfiguraatio sisältää vain joitain niistä, käynnistys epäonnistuu ja ilmoittaa, mitkä ominaisuudet puuttuvat.
Jokainen selain tilaa yhden avaintparin. Jos avaimet muuttuvat, push-palvelu hylkää olemassa olevat tilaukset. Seuraava subscribe()-kutsu jokaisessa selaimessa korvataa sen tilauksen.
Kuinka se toimii
Prosessissa on kolme vaihetta:
- Tilaa. Näkymästä,
Push.getCurrent().subscribe()pyytää käyttäjän lupaa ja palauttaaPushSubscription:n, joka tunnistaa selaimen osoitteen. - Tallenna. Sovellus tallentaa tilauksen sen tietojen kanssa ja liittää sen vastaavaan käyttäjään.
- Lähetä. Myöhemmin mistä tahansa säikeestä,
PushSender.send(subscription, message)siirtää viestin selaimen valmistajan push-palveluun. Palvelu näyttää ilmoituksen riippumatta siitä, onko sovellus auki vai ei.
Push.getCurrent().subscribe().thenAccept(subscriptions::save);
sender.send(subscription,
PushMessage.create("Tilauksesi on lähetetty").setUrl("/orders/42").build());
Seuraavat osiot selittävät, mitä selain näyttää ja kuinka käsitellä epäonnistumisia jokaisessa vaiheessa.
Instanssi
Hanki push-instanssi nykyisestä ympäristöstä:
import com.webforj.push.Push;
Push push = Push.getCurrent();
if (Push.isPresent()) {
// ...
}
Push.ifPresent(p -> {
// ...
});
Selaimen tilaaminen
Kutsu subscribe() käyttäjän toimintaan vastaamiseksi, kuten napsauttamalla "Ota ilmoitukset käyttöön" -painiketta. Palatettu PendingResult valmistuu selaimen PushSubscription:lla. Jos selain ei voi tilata, se valmistuu poikkeuksellisesti WebforjPushException -poikkeuksella.
PendingResult<PushSubscription> request = Push.getCurrent().subscribe();
request.thenAccept(subscription -> {
subscriptions.save(subscription);
});
request.exceptionally(throwable -> {
WebforjPushException error = (WebforjPushException) throwable.getCause();
PushStatus status = error.getStatus();
String message = error.getMessage();
return null;
});
Jos selain on jo tilattu, subscribe()-kutsumisen palauttaa olemassa olevan tilauksen. Voit siis kutsua sitä turvallisesti jokaisella vierailulla.
Ensimmäinen subscribe()-kutsu pyytää käyttäjältä lupaa. Selain näyttää tämän kehotteen, se ei ole osa sovelluksen UI:ta. Koska selaimet näyttävät kehotteen vain käyttäjän toimintaan vastauksena, kutsu subscribe() napsautustunnistimesta sen sijaan, että sen näkymän rakentajasta.
Jos käyttäjä estää kehotteen, sovellus ei voi pyytää uudelleen kyseisestä alkuperästä.
Tilausten tallentaminen
Tilauksen osoittaa yhden selaimen osoitteen ja kuuluu palvelimelle. Tallenna se sovelluksen tietojen kanssa, käyttäen sen päätepistettä avaimena. Sisällytä kaikki tiedot, joita sovellus tarvitsee valitakseen sopivat selaimet myöhemmin, kuten liitetty käyttäjä. Jokainen tilaus sisältää kolme tekstiarvoa:
| Arvo | Merkitys |
|---|---|
getEndpoint() | Toimitus-URL, jonka selainvalmistajan push-palvelu on määrittänyt |
getP256dh() | Selaimen julkinen avain |
getAuth() | Selaimen todennussalaisuus |
Käyttäjä, joka tilaa kahdesta selainympäristöstä, on kahdelle tilaukselle. Poista tilaus, kun sen selain peruuttaa tai kun lähetys ilmoittaa, että se on vanhentunut. Katso Epäonnistumisen tila.
Tilauksen palauttaminen
getSubscription() palauttaa selaimen nykyisen tilauksen tai tyhjän tuloksen, jos sellaista ei ole. Käytä sitä synkronoimaan palvelimen kopio esimerkiksi sen jälkeen, kun sovelluksen tallennus on nollattu:
Push.getCurrent().getSubscription().thenAccept(existing -> {
existing.ifPresent(subscriptions::save);
});
PushPermission kautta, getPermission() raportoi, myönnettiinkö käyttäjälle lupa, estettiinkö se vai onko käyttäjä vielä vastannut ilmoituskehotteeseen. Käytä tätä tulosta piilottaaksesi "Ota ilmoitukset käyttöön" -painike, kun napsauttaminen ei vaikuttaisi.
Peruuttaminen
unsubscribe() peruuttaa selaimen tilauksen. Se valmistuu poistetulla tilauksella, jotta sovellus voi poistaa sen tallennetun kopion, tai tyhjällä tuloksella, jos selaimella ei ollut tilausta.
Push.getCurrent().unsubscribe().thenAccept(removed -> {
removed.ifPresent(subscriptions::delete);
});
Ilmoitusten lähettäminen
PushSender lähettää PushMessage:n tallennettuun tilaukseen. Se allekirjoittaa viestin käyttöönoton avaimilla ja siirtää sen selaimen valmistajan push-palveluun. Tämä palvelu herättää selaimen ja näyttää ilmoituksen. Koska operaatio ei koskaan blokkaa kutsuvaa säiettä, voit kutsua sen napsautustunnistimesta, ajoitetusta työstä tai pyyntöjen käsittelijästä.
Kun ominaisuudet on konfiguroitu, lähettäjä on saatavilla beanina, jonka voit sisällyttää näkymiin, palveluihin ja ajoitettuihin tehtäviin. Korvataaksesi sen, määritä oma PushSender-bean.
@Route("/orders")
public class OrdersView extends Composite<FlexLayout> {
public OrdersView(PushSender sender, PushSubscriptions subscriptions) {
// ...
}
}
Ilman Springiä, new PushSender() lukee avaimet sovelluksen konfiguraatiosta. Luo lähettäjä sovellus-threadissä, joko näkymässä tai App.run():ssa, ja käytä sitä sitten mistä tahansa säikeestä. Kaikki lähettäjät jakavat yhden yhteysaltaan push-palveluille, joten niiden luominen missä tahansa ei aiheuta kustannuksia.
Ilmoituksia, jotka on lähetettävä myöhemmin tai sen jälkeen, kun käyttäjä on poistunut, käytä ajastinta palvelimella, kuten Springin TaskScheduler. Älä käytä sivun ajastinta kuten Interval, koska se pysähtyy, kun välilehti suljetaan.
Viestin muodostaminen
Luo viesti sen otsikoilla, ja määritä sitten kaikki muut vaihtoehdot rakentajassa:
PushMessage message = PushMessage.create("Tilauksesi on lähetetty")
.setBody("Tilauksesi #42 on matkalla")
.setIcon("icons://icon-192x192.png")
.setUrl("/orders/42")
.setActions(List.of(new PushAction("track", "Seuraa", "/orders/42/tracking")))
.build();
PendingResult<Void> sent = sender.send(subscription, message);
sent.thenAccept(v -> status.setText("Lähetetty"));
sent.exceptionally(throwable -> {
WebforjPushException error = (WebforjPushException) throwable;
status.setText(error.getStatus() + ": " + error.getMessage());
return null;
});
send() palauttaa heti. PendingResult valmistuu, kun push-palvelu hyväksyy viestin, tai valmistuu poikkeuksellisesti, jos palvelu ei hyväksy sitä. Jos send() kutsutaan sovellus-threadissä, kuten kuuntimen kautta, sen palautteet suoritetaan siinä säikeessä ja voivat päivittää komponentteja. Jos istunto, joka kutsui send()-toimintoa, päättyy ennen kuin vastaus saapuu, palautteet eivät suoriteta, mutta ilmoitus toimitetaan silti.
Lähetys odottaa enintään 30 sekuntia push-palvelua ennen kuin se epäonnistuu UNREACHABLE-tilassa. Käytä setTimeout(Duration) muuttaaksesi aikarajaa jokaiselle lähetykselle.
| Vaihtoehto | Vaikutus |
|---|---|
setBody | Asettaa tekstin, joka näkyy otsikon alapuolella |
setIcon | Asettaa ilmoituksen yhteydessä näytettävän kuvan. Se hyväksyy absoluuttiset URL-osoitteet sekä icons:// ja ws:// protokollat. Katso Resurssit. Se ei hyväksy context:// protokollaa, koska push-palvelut rajoittavat viestin 4 kB:hen |
setUrl | Asettaa sivun, joka avautuu, kun käyttäjä napsauttaa ilmoitusta. Suhteelliset URL-osoitteet ratkaistaan sovelluksen juurta vasten. Jos URL-osoitetta ei aseteta, avautuu sovelluksen juuressa |
setActions | Asettaa ilmoituksessa näytettävät painikkeet, joissa jokaiselle painikkeelle on erillinen URL-osoite. Katso Selaintuki |
setTag | Asettaa tunnisteen. Jos näytettävällä ilmoituksella on sama tunniste, uusi ilmoitus korvataan sille |
setSilent | Näyttää ilmoituksen ilman ääntä tai värinää |
setTimeToLive | Asettaa kuinka kauan push-palvelu säilyttää viestin offline-laitteelle, enintään neljä viikkoa |
setUrgency | Käyttää PushUrgency ilmoittamaan laitteelle, että se voi viivästyttää alhaisen kiireellisyyden viestejä ja säästää akkua |
setTopic | Korvata viesti, joka odottaa vielä push-palvelussa, kun molemmat viestit sisältävät saman aiheen. Aiheet voivat sisältää enintään 32 merkkiä, jotka ovat URL:ssä turvallisia |
Kun välilehti jo näyttää sivua, ilmoituksen napsauttaminen keskittyy sovellukseen. Muussa tapauksessa sivu avataan uudessa välilehdessä. Napsauttaessasi ilmoituksen painiketta avataan sen URL samalla tavalla.
Jokainen viesti näyttää ilmoituksen. Koska selaimet eivät herätä sivua viestille, joka ei näytä mitään, push-palveluja ei voida käyttää hiljaisten tietopäivitysten lähettämiseen.
Epäonnistumisen tila
Kun subscribe() tai send() epäonnistuu, sen PendingResult ilmoittaa WebforjPushException:sta. PushStatus tunnistaa syyn:
| Tila | Milloin | Mitä tehdä |
|---|---|---|
PERMISSION_DENIED | Käyttäjä on estänyt ilmoitukset sovellukselle | Selitä, mistä käyttäjä voi sallia ilmoitukset selaimen asetuksissa |
UNSUPPORTED | Push ei ole tuettu selaimessa, sivu ei ole suojatussa kontekstissa tai sovellusta ei ole otettu käyttöön servletinä | Piilota toiminto |
NOT_CONFIGURED | Ainakin yksi webforj.push.* -ominaisuus puuttuu tai on puutteellinen | Luo avaimet ja konfiguroi kaikki kolme ominaisuutta |
SUBSCRIPTION_EXPIRED | Push-palvelu ei enää tunnista tilausta, koska käyttäjä peruutti tai asensi selaimen uudelleen | Poista tallennettu tilaus |
REJECTED | Push-palvelu hylkäsi viestin; getStatusCode() sisältää sen vastauksen | Vahvista avaimet ja viestin koko |
UNREACHABLE | Push-palvelu ei vastannut ennen aikarajan umpeutumista | Yritä myöhemmin uudelleen |
UNKNOWN | Tallennettu päätepiste ei ole voimassa oleva URL, tai tilausta tai viestiä ei voitu koodata | Vahvista tallennettu tilaus |
Poista vanhentuneet tilaukset jokaisen lähetyksen aikana:
sender.send(subscription, message).exceptionally(throwable -> {
WebforjPushException error = (WebforjPushException) throwable;
if (error.getStatus() == PushStatus.SUBSCRIPTION_EXPIRED) {
subscriptions.delete(subscription);
}
return null;
});
Push-palvelut poistoilmoittavat tilausten laiskasti. Ne hyväksyvät edelleen ensimmäisen viestin sen jälkeen, kun käyttäjä on perunut, mutta se ei mene minnekään. Seuraava viesti ilmoittaa SUBSCRIPTION_EXPIRED. Hyväksytty lähetys tarkoittaa, että viesti saavutti push-palvelun, ei sitä, että käyttäjä näki sen.
Selaintuki
Kaikki tärkeimmät työpöytä- ja mobiiliselaimet näyttävät push-ilmoituksia tilattaessa. Pidä nämä rajoitukset mielessä:
- iPhoneilla ja iPadeilla push toimii vain web-sovelluksille, jotka on lisätty Koti-näyttöön iOS 16.4:ssä tai sitä uudemmassa versiossa. Safari-välilehdessä
subscribe()raportoiUNSUPPORTED. Katso Asennettavat sovellukset vaaditulle sovellussuunnitelmalle. - Safari ei näytä ilmoituspainikkeita. Se näyttää viestejä toiminnoilla ilman painikkeitaan, mutta napsauttamalla ilmoitusta avataan edelleen viestin URL.
- Android- ja iOS-web-näkymät eivät näytä ilmoituksia.
Lisätietoja selaimittain, katso MDN showNotification-yhteensopivuus-taulukko.
Täydellinen esimerkki
Seuraava näkymä tilaa ja peruuttaa selaimen, tallentaa tilaukset muistiin ja lähettää viestin jokaiselle tallennetulle tilaukselle. Se voi lähettää heti tai odottaa kahdeksan sekuntia käyttämällä Springin TaskScheduler:ia, jolloin välilehti voi sulkeutua ennen ilmoituksen saapumista. Sovellusluokka käyttää @EnableScheduling -komentoa, jotta aikatauluttaja on saatavilla.
package com.example;
import com.webforj.push.PushSubscription;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.stereotype.Service;
@Service
public class PushSubscriptions {
private final Map<String, PushSubscription> byEndpoint = new ConcurrentHashMap<>();
public void save(PushSubscription subscription) {
byEndpoint.put(subscription.getEndpoint(), subscription);
}
public void delete(PushSubscription subscription) {
byEndpoint.remove(subscription.getEndpoint());
}
public Collection<PushSubscription> findAll() {
return byEndpoint.values();
}
}