Pushy adalah perpustakaan Java untuk mengirimkan pemberitahuan push APN (iOS, macOS, dan Safari).
Pushy mengirimkan pemberitahuan push menggunakan protokol APN berbasis HTTP/2 Apple dan mendukung autentikasi berbasis TLS dan token. Ini membedakan dirinya dari perpustakaan pemberitahuan push lainnya dengan fokus pada dokumentasi menyeluruh, operasi asinkron, dan desain untuk operasi skala industri. Dengan Pushy, mudah dan efisien untuk memelihara beberapa koneksi paralel ke gateway APN untuk mengirimkan notifikasi dalam jumlah besar ke banyak aplikasi berbeda ("topik").
Kami percaya bahwa Pushy sudah menjadi alat terbaik untuk mengirimkan pemberitahuan push APN dari aplikasi Java, dan kami berharap Anda membantu kami menjadikannya lebih baik melalui laporan bug dan permintaan penarikan.
Jika Anda memerlukan aplikasi GUI sederhana untuk mengirimkan pemberitahuan push untuk tujuan pengembangan atau pengujian, Anda mungkin juga tertarik dengan proyek saudara Pushy, Pushy Console.
Jika Anda menggunakan Maven, Anda dapat menambahkan Pushy ke proyek Anda dengan menambahkan deklarasi ketergantungan berikut ke POM Anda:
< dependency >
< groupId >com.eatthepath</ groupId >
< artifactId >pushy</ artifactId >
< version >0.15.4</ version >
</ dependency >
Jika Anda tidak menggunakan Maven (atau sesuatu yang memahami dependensi Maven, seperti Gradle), Anda dapat mengunduh Pushy sebagai file .jar
dan menambahkannya ke proyek Anda secara langsung. Anda juga harus memastikan bahwa Anda memiliki dependensi runtime Pushy di classpath Anda. Mereka adalah:
Pushy sendiri memerlukan Java 8 atau lebih baru untuk membangun dan menjalankannya. Meskipun tidak diwajibkan, pengguna dapat memilih untuk menggunakan netty-native sebagai penyedia SSL untuk meningkatkan kinerja. Untuk menggunakan penyedia asli, pastikan netty-tcnative ada di classpath Anda. Pengguna Maven dapat menambahkan ketergantungan pada proyek mereka sebagai berikut:
< dependency >
< groupId >io.netty</ groupId >
< artifactId >netty-tcnative-boringssl-static</ artifactId >
< version >2.0.62.Final</ version >
< scope >runtime</ scope >
</ dependency >
Sebelum Anda dapat mulai menggunakan Pushy, Anda perlu melakukan beberapa pekerjaan penyediaan dengan Apple untuk mendaftarkan aplikasi Anda dan mendapatkan sertifikat atau kunci penandatanganan yang diperlukan (lebih lanjut tentang ini akan segera dibahas). Untuk detail mengenai proses ini, silakan lihat bagian Mendaftarkan Aplikasi Anda dengan APN pada dokumentasi UserNotifications Apple. Harap diperhatikan bahwa ada beberapa peringatan, khususnya pada macOS 10.13 (El Capitan).
Secara umum, klien APN harus melakukan autentikasi dengan server APN melalui beberapa cara sebelum mereka dapat mengirim pemberitahuan push. Saat ini, APN (dan Pushy) mendukung dua metode autentikasi: autentikasi berbasis TLS dan autentikasi berbasis token. Kedua pendekatan ini saling eksklusif; Anda harus memilih satu atau yang lain untuk setiap klien.
Dalam autentikasi berbasis TLS, klien memberikan sertifikat TLS ke server saat menyambungkan, dan dapat mengirimkan pemberitahuan ke "topik" apa pun yang disebutkan dalam sertifikat. Secara umum, ini berarti satu klien hanya dapat mengirimkan pemberitahuan push ke satu aplikasi penerima.
Setelah Anda mendaftarkan aplikasi dan memiliki sertifikat yang diperlukan, hal pertama yang perlu Anda lakukan untuk mulai mengirimkan pemberitahuan push dengan Pushy adalah membuat ApnsClient
. Klien yang menggunakan autentikasi TLS memerlukan sertifikat dan kunci pribadi untuk mengautentikasi dengan server APN. Cara paling umum untuk menyimpan sertifikat dan kunci adalah dalam file PKCS#12 yang dilindungi kata sandi (Anda akan mendapatkan file .p12 yang dilindungi kata sandi jika Anda mengikuti instruksi Apple pada saat penulisan ini). Untuk membuat klien yang akan menggunakan otentikasi berbasis TLS:
final ApnsClient apnsClient = new ApnsClientBuilder ()
. setApnsServer ( ApnsClientBuilder . DEVELOPMENT_APNS_HOST )
. setClientCredentials ( new File ( "/path/to/certificate.p12" ), "p12-file-password" )
. build ();
Dalam autentikasi berbasis token, klien masih menyambung ke server menggunakan sambungan aman TLS, namun tidak memberikan sertifikat ke server saat menyambung. Sebaliknya, klien menyertakan token yang ditandatangani secara kriptografis dengan setiap notifikasi yang mereka kirim (jangan khawatir—Pushy akan menangani ini untuk Anda secara otomatis). Klien dapat mengirimkan pemberitahuan push ke "topik" apa pun yang memiliki kunci penandatanganan yang valid.
Untuk memulai klien berbasis token, Anda perlu mendapatkan kunci penandatanganan (juga disebut kunci pribadi dalam beberapa konteks) dari Apple. Setelah Anda memiliki kunci penandatanganan, Anda dapat membuat klien baru:
final ApnsClient apnsClient = new ApnsClientBuilder ()
. setApnsServer ( ApnsClientBuilder . DEVELOPMENT_APNS_HOST )
. setSigningKey ( ApnsSigningKey . loadFromPkcs8File ( new File ( "/path/to/key.p8" ),
"TEAMID1234" , "KEYID67890" ))
. build ();
Klien APN Pushy memelihara kumpulan koneksi internal ke server APN dan membuat koneksi baru sesuai permintaan. Akibatnya, klien tidak perlu memulai secara eksplisit. Terlepas dari metode autentikasi yang Anda pilih, setelah Anda membuat klien, klien siap untuk mulai mengirimkan pemberitahuan push. Minimal, notifikasi push memerlukan token perangkat (yang mengidentifikasi perangkat tujuan notifikasi dan merupakan ide yang berbeda dari token autentikasi), topik, dan payload.
final SimpleApnsPushNotification pushNotification ;
{
final ApnsPayloadBuilder payloadBuilder = new SimpleApnsPayloadBuilder ();
payloadBuilder . setAlertBody ( "Example!" );
final String payload = payloadBuilder . build ();
final String token = TokenUtil . sanitizeTokenString ( "<efc7492 bdbd8209>" );
pushNotification = new SimpleApnsPushNotification ( token , "com.example.myApp" , payload );
}
Pushy menyertakan SimpleApnsPayloadBuilder
, dan pembuat muatan berdasarkan Gson dan Jackson tersedia sebagai modul terpisah. Payload APN hanyalah string JSON, dan penelepon dapat menghasilkan payload dengan metode pilihan mereka; Meskipun pembuat muatan Pushy mungkin nyaman, penelepon tidak diwajibkan untuk menggunakannya.
Proses pengiriman pemberitahuan push tidak sinkron; meskipun proses pengiriman pemberitahuan dan mendapatkan balasan dari server mungkin memerlukan waktu, klien akan segera mengembalikan CompletableFuture
. Anda dapat menggunakan CompletableFuture
untuk melacak kemajuan dan hasil akhir dari operasi pengiriman. Perhatikan bahwa pengiriman notifikasi akan mengembalikan PushNotificationFuture
, yang merupakan subkelas CompletableFuture
yang selalu menyimpan referensi ke notifikasi yang dikirimkan.
final PushNotificationFuture < SimpleApnsPushNotification , PushNotificationResponse < SimpleApnsPushNotification >>
sendNotificationFuture = apnsClient . sendNotification ( pushNotification );
CompletableFuture
akan selesai dalam salah satu dari tiga keadaan:
CompletableFuture
gagal dengan pengecualian. Hal ini umumnya dianggap sebagai kegagalan sementara, dan penelepon harus mencoba mengirimkan pemberitahuan lagi ketika masalah telah teratasi.Contoh:
try {
final PushNotificationResponse < SimpleApnsPushNotification > pushNotificationResponse =
sendNotificationFuture . get ();
if ( pushNotificationResponse . isAccepted ()) {
System . out . println ( "Push notification accepted by APNs gateway." );
} else {
System . out . println ( "Notification rejected by the APNs gateway: " +
pushNotificationResponse . getRejectionReason ());
pushNotificationResponse . getTokenInvalidationTimestamp (). ifPresent ( timestamp -> {
System . out . println ( " t …and the token is invalid as of " + timestamp );
});
}
} catch ( final ExecutionException e ) {
System . err . println ( "Failed to send push notification." );
e . printStackTrace ();
}
Penting untuk dicatat bahwa CompletableFuture
memiliki kemampuan untuk menjadwalkan tugas tambahan agar dijalankan ketika operasi selesai. Menunggu setiap pemberitahuan push individual tidak efisien dalam praktiknya, dan sebagian besar pengguna akan lebih baik dilayani dengan menambahkan tugas tindak lanjut ke CompletableFuture
daripada memblokir hingga selesai. Sebagai contoh:
sendNotificationFuture . whenComplete (( response , cause ) -> {
if ( response != null ) {
// Handle the push notification response as before from here.
} else {
// Something went wrong when trying to send the notification to the
// APNs server. Note that this is distinct from a rejection from
// the server, and indicates that something went wrong when actually
// sending the notification or waiting for a reply.
cause . printStackTrace ();
}
});
Semua klien APN—bahkan klien yang belum pernah mengirim pesan—dapat mengalokasikan dan menyimpan sumber daya sistem, dan penting untuk melepaskannya. Klien APN dimaksudkan untuk menjadi sumber daya yang persisten dan berumur panjang; Anda pastinya tidak perlu mematikan klien setelah mengirimkan pemberitahuan (atau bahkan kumpulan pemberitahuan), namun Anda ingin mematikan klien (atau klien) ketika aplikasi Anda dimatikan:
final CompletableFuture < Void > closeFuture = apnsClient . close ();
Saat dimatikan, klien akan menunggu semua notifikasi terkirim tetapi tidak diakui untuk menerima balasan dari server. Notifikasi yang telah diteruskan ke sendNotification
tetapi belum dikirim ke server (yaitu notifikasi yang menunggu dalam antrean internal) akan langsung gagal saat sambungan terputus. Penelepon umumnya harus memastikan bahwa semua pemberitahuan yang dikirim telah diakui oleh server sebelum dimatikan.
Memaksimalkan sumber daya sistem Anda untuk aplikasi dengan throughput tinggi selalu membutuhkan usaha. Untuk memandu Anda melalui proses ini, kami telah menyusun halaman wiki yang mencakup beberapa praktik terbaik dalam menggunakan Pushy. Semua poin ini dibahas lebih rinci di wiki, namun secara umum, rekomendasi kami adalah:
ApnsClient
sebagai sumber daya yang berumur panjangCompletableFutures
jika Anda ingin melacak status pemberitahuan push Anda Pushy menyertakan antarmuka untuk memantau metrik yang memberikan wawasan tentang perilaku dan kinerja klien. Anda dapat menulis implementasi antarmuka ApnsClientMetricsListener
Anda sendiri untuk mencatat dan melaporkan metrik. Kami juga menyediakan pemroses metrik yang mengumpulkan dan melaporkan metrik menggunakan pustaka Metrik Dropwizard dan menggunakan fasad pemantauan aplikasi Mikrometer sebagai modul terpisah. Untuk mulai menerima metrik, tetapkan pemroses saat membuat klien baru:
final ApnsClient apnsClient = new ApnsClientBuilder ()
. setApnsServer ( ApnsClientBuilder . DEVELOPMENT_APNS_HOST )
. setSigningKey ( ApnsSigningKey . loadFromPkcs8File ( new File ( "/path/to/key.p8" ),
"TEAMID1234" , "KEYID67890" ))
. setMetricsListener ( new MyCustomMetricsListener ())
. build ();
Harap perhatikan bahwa metode penanganan metrik dalam implementasi pendengar Anda tidak boleh memanggil kode pemblokiran. Sangat tepat untuk menaikkan penghitung secara langsung dalam metode handler, namun panggilan ke database atau titik akhir pemantauan jarak jauh harus dikirim ke thread terpisah.
Jika Anda perlu menggunakan proksi untuk koneksi keluar, Anda dapat menentukan ProxyHandlerFactory
saat membuat instans ApnsClient
Anda. Implementasi nyata dari ProxyHandlerFactory
disediakan untuk proxy HTTP, SOCKS4, dan SOCKS5.
Contoh:
final ApnsClient apnsClient = new ApnsClientBuilder ()
. setApnsServer ( ApnsClientBuilder . DEVELOPMENT_APNS_HOST )
. setSigningKey ( ApnsSigningKey . loadFromPkcs8File ( new File ( "/path/to/key.p8" ),
"TEAMID1234" , "KEYID67890" ))
. setProxyHandlerFactory ( new Socks5ProxyHandlerFactory (
new InetSocketAddress ( "my.proxy.com" , 1080 ), "username" , "password" ))
. build ();
Jika menggunakan proksi HTTP yang dikonfigurasi melalui properti sistem JVM, Anda juga dapat menggunakan:
final ApnsClient apnsClient = new ApnsClientBuilder ()
. setApnsServer ( ApnsClientBuilder . DEVELOPMENT_APNS_HOST )
. setSigningKey ( ApnsSigningKey . loadFromPkcs8File ( new File ( "/path/to/key.p8" ),
"TEAMID1234" , "KEYID67890" ))
. setProxyHandlerFactory ( HttpProxyHandlerFactory . fromSystemProxies (
ApnsClientBuilder . DEVELOPMENT_APNS_HOST ))
. build ();
Pushy menggunakan SLF4J untuk login. Jika Anda belum terbiasa dengannya, SLF4J adalah fasad yang memungkinkan pengguna memilih pustaka logging mana yang akan digunakan pada waktu penerapan dengan menambahkan "pengikatan" khusus ke jalur kelas. Untuk menghindari membuat pilihan untuk Anda, Pushy sendiri tidak bergantung pada binding SLF4J apa pun; Anda harus menambahkannya sendiri (baik dengan menambahkannya sebagai ketergantungan pada proyek Anda sendiri atau dengan menginstalnya secara langsung). Jika Anda tidak memiliki binding SLF4J di classpath Anda, Anda mungkin akan melihat peringatan seperti ini:
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Untuk informasi lebih lanjut, lihat panduan pengguna SLF4J.
Pushy menggunakan level logging sebagai berikut:
Tingkat | Peristiwa dicatat |
---|---|
error | Kesalahan serius yang tidak dapat diperbaiki; kesalahan yang dapat dipulihkan yang kemungkinan mengindikasikan bug di Pushy |
warn | Kesalahan serius namun dapat diperbaiki; kesalahan yang mungkin menunjukkan bug dalam kode pemanggil |
info | Peristiwa siklus hidup yang penting |
debug | Peristiwa siklus hidup kecil; pengecualian yang diharapkan |
trace | Operasi IO individu |
Pushy menyertakan server APN tiruan yang dapat digunakan penelepon dalam pengujian integrasi dan tolok ukur. Tidak perlu menggunakan server tiruan (atau kelas terkait lainnya) dalam operasi normal.
Untuk membangun server tiruan, penelepon harus menggunakan MockApnsServerBuilder
. Semua server memerlukan PushNotificationHandler
(dibuat oleh PushNotificationHandlerFactory
yang disediakan untuk pembuat) yang memutuskan apakah server tiruan akan menerima atau menolak setiap pemberitahuan push yang masuk. Pushy menyertakan AcceptAllPushNotificationHandlerFactory
yang berguna untuk pembandingan dan ValidatingPushNotificationHandlerFactory
yang mungkin berguna untuk pengujian integrasi.
Penelepon juga dapat menyediakan MockApnsServerListener
saat membangun server tiruan; pendengar diberitahu setiap kali server tiruan menerima atau menolak pemberitahuan dari klien.
Pushy tersedia di bawah Lisensi MIT.
Versi Pushy saat ini adalah 0.15.4. Ini berfungsi penuh dan banyak digunakan di lingkungan produksi, namun API publik mungkin berubah secara signifikan sebelum rilis 1.0.