Pushy هي مكتبة Java لإرسال إشعارات الدفع الخاصة بـ APNs (iOS وmacOS وSafari).
يرسل Pushy إشعارات الدفع باستخدام بروتوكول APNs المستند إلى HTTP/2 من Apple ويدعم كلاً من TLS والمصادقة المستندة إلى الرمز المميز. إنه يميز نفسه عن مكتبات إشعارات الدفع الأخرى مع التركيز على التوثيق الشامل والتشغيل غير المتزامن والتصميم للتشغيل على نطاق صناعي. مع Pushy، من السهل والفعال الاحتفاظ باتصالات متوازية متعددة ببوابة APNs لإرسال عدد كبير من الإشعارات إلى العديد من التطبيقات المختلفة ("المواضيع").
نعتقد أن Pushy هي بالفعل أفضل أداة لإرسال إشعارات APNs من تطبيقات Java، ونأمل أن تساعدنا في تحسينها من خلال تقارير الأخطاء وطلبات السحب.
إذا كنت بحاجة إلى تطبيق واجهة مستخدم رسومية بسيط لإرسال إشعارات الدفع لأغراض التطوير أو الاختبار، فقد تكون مهتمًا أيضًا بمشروع Pushy الشقيق، Pushy Console.
إذا كنت تستخدم Maven، يمكنك إضافة Pushy إلى مشروعك عن طريق إضافة إعلان التبعية التالي إلى POM الخاص بك:
< dependency >
< groupId >com.eatthepath</ groupId >
< artifactId >pushy</ artifactId >
< version >0.15.4</ version >
</ dependency >
إذا كنت لا تستخدم Maven (أو أي شيء آخر يفهم تبعيات Maven، مثل Gradle)، فيمكنك تنزيل Pushy كملف .jar
وإضافته إلى مشروعك مباشرةً. ستحتاج أيضًا إلى التأكد من أن لديك تبعيات وقت تشغيل Pushy على مسار الفصل الدراسي الخاص بك. هم:
يتطلب Pushy نفسه Java 8 أو أحدث للإنشاء والتشغيل. على الرغم من أن ذلك ليس مطلوبًا، إلا أنه يمكن للمستخدمين اختيار استخدام netty-native كموفر SSL لتحسين الأداء. لاستخدام موفر أصلي، تأكد من وجود netty-tcnative على مسار الفصل الخاص بك. يمكن لمستخدمي Maven إضافة تبعية إلى مشروعهم على النحو التالي:
< dependency >
< groupId >io.netty</ groupId >
< artifactId >netty-tcnative-boringssl-static</ artifactId >
< version >2.0.62.Final</ version >
< scope >runtime</ scope >
</ dependency >
قبل أن تتمكن من البدء في استخدام Pushy، ستحتاج إلى القيام ببعض أعمال التوفير مع Apple لتسجيل تطبيقك والحصول على الشهادات المطلوبة أو مفاتيح التوقيع (المزيد حول ذلك قريبًا). للحصول على تفاصيل حول هذه العملية، يرجى الاطلاع على قسم تسجيل تطبيقك باستخدام APNs في وثائق UserNotifications الخاصة بشركة Apple. يرجى ملاحظة أن هناك بعض التحذيرات، خاصة في ظل نظام التشغيل macOS 10.13 (El Capitan).
بشكل عام، يجب على عملاء APNs المصادقة مع خادم APNs ببعض الوسائل قبل أن يتمكنوا من إرسال إشعارات الدفع. حاليًا، تدعم APNs (و Pushy) طريقتين للمصادقة: المصادقة المستندة إلى TLS والمصادقة المستندة إلى الرمز المميز. النهجان يستبعد كل منهما الآخر. ستحتاج إلى اختيار واحد أو آخر لكل عميل.
في المصادقة المستندة إلى TLS، يقدم العملاء شهادة TLS إلى الخادم عند الاتصال، ويمكنهم إرسال إشعارات إلى أي "موضوع" مذكور في الشهادة. بشكل عام، هذا يعني أنه يمكن للعميل الواحد فقط إرسال إشعارات الدفع إلى تطبيق استقبال واحد.
بمجرد تسجيل تطبيقك والحصول على الشهادات المطلوبة، فإن أول شيء عليك القيام به لبدء إرسال الإشعارات الفورية باستخدام Pushy هو إنشاء ApnsClient
. يحتاج العملاء الذين يستخدمون مصادقة TLS إلى شهادة ومفتاح خاص للمصادقة مع خادم APNs. الطريقة الأكثر شيوعًا لتخزين الشهادة والمفتاح هي في ملف PKCS#12 محمي بكلمة مرور (سينتهي بك الأمر بملف .p12 محمي بكلمة مرور إذا اتبعت تعليمات Apple في وقت كتابة هذا المقال). لإنشاء عميل يستخدم المصادقة المستندة إلى TLS:
final ApnsClient apnsClient = new ApnsClientBuilder ()
. setApnsServer ( ApnsClientBuilder . DEVELOPMENT_APNS_HOST )
. setClientCredentials ( new File ( "/path/to/certificate.p12" ), "p12-file-password" )
. build ();
في المصادقة المستندة إلى الرمز المميز، يستمر العملاء في الاتصال بالخادم باستخدام اتصال TLS آمن، لكنهم لا يقدمون شهادة إلى الخادم عند الاتصال. وبدلاً من ذلك، يقوم العملاء بتضمين رمز مميز موقّع بالتشفير مع كل إشعار يرسلونه (لا تقلق، إذ يتعامل Pushy مع هذا نيابةً عنك تلقائيًا). يمكن للعملاء إرسال إشعارات الدفع إلى أي "موضوع" لديهم مفتاح توقيع صالح له.
للبدء مع عميل يعتمد على الرمز المميز، ستحتاج إلى الحصول على مفتاح توقيع (يُسمى أيضًا المفتاح الخاص في بعض السياقات) من Apple. بمجرد حصولك على مفتاح التوقيع، يمكنك إنشاء عميل جديد:
final ApnsClient apnsClient = new ApnsClientBuilder ()
. setApnsServer ( ApnsClientBuilder . DEVELOPMENT_APNS_HOST )
. setSigningKey ( ApnsSigningKey . loadFromPkcs8File ( new File ( "/path/to/key.p8" ),
"TEAMID1234" , "KEYID67890" ))
. build ();
يحتفظ عملاء APNs الخاصين بـ Pushy بمجموعة داخلية من الاتصالات بخادم APNs ويقومون بإنشاء اتصالات جديدة عند الطلب. ونتيجة لذلك، لا يحتاج العملاء إلى البدء بشكل صريح. بغض النظر عن طريقة المصادقة التي تختارها، بمجرد إنشاء العميل، يصبح جاهزًا لبدء إرسال الإشعارات. على الأقل، تحتاج الإشعارات الفورية إلى رمز مميز للجهاز (الذي يحدد جهاز وجهة الإشعار وهو فكرة مختلفة عن رمز المصادقة)، وموضوع، وحمولة.
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 على SimpleApnsPayloadBuilder
، وتتوفر أدوات إنشاء الحمولة المستندة إلى Gson وJackson كوحدات منفصلة. حمولات APNs هي مجرد سلاسل JSON، ويمكن للمتصلين إنتاج حمولات بالطريقة التي يختارونها؛ في حين أن منشئي الحمولة النافعة في Pushy قد يكونون مناسبين، إلا أن المتصلين غير ملزمين باستخدامها.
عملية إرسال إشعار الدفع غير متزامنة؛ على الرغم من أن عملية إرسال إشعار والحصول على رد من الخادم قد تستغرق بعض الوقت، إلا أن العميل سيعيد CompletableFuture
على الفور. يمكنك استخدام CompletableFuture
لتتبع التقدم والنتيجة النهائية لعملية الإرسال. لاحظ أن إرسال إشعار يؤدي إلى إرجاع PushNotificationFuture
، وهو فئة فرعية من CompletableFuture
والتي تحتوي دائمًا على مرجع للإشعار الذي تم إرساله.
final PushNotificationFuture < SimpleApnsPushNotification , PushNotificationResponse < SimpleApnsPushNotification >>
sendNotificationFuture = apnsClient . sendNotification ( pushNotification );
سوف يكتمل CompletableFuture
في واحدة من ثلاث حالات:
CompletableFuture
مع استثناء. يجب اعتبار هذا فشلًا مؤقتًا بشكل عام، ويجب أن يحاول المتصلون إرسال الإشعار مرة أخرى عندما يتم حل المشكلة.مثال:
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 ();
}
من المهم ملاحظة أن CompletableFuture
لديه إمكانيات لجدولة مهام إضافية ليتم تشغيلها عند اكتمال العملية. يعد انتظار كل إشعار دفع فردي أمرًا غير فعال من الناحية العملية، وسيتم تقديم خدمة أفضل لمعظم المستخدمين عن طريق إضافة مهام متابعة إلى CompletableFuture
بدلاً من الحظر حتى يكتمل. كمثال:
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 ();
}
});
يمكن لجميع عملاء APNs - حتى أولئك الذين لم يرسلوا رسالة مطلقًا - تخصيص موارد النظام والاحتفاظ بها، ومن المهم تحريرها. يُقصد من عملاء APN أن يكونوا موارد مستمرة وطويلة العمر؛ من المؤكد أنك لا تحتاج إلى إيقاف تشغيل العميل بعد إرسال إشعار (أو حتى مجموعة من الإشعارات)، ولكنك ستحتاج إلى إيقاف تشغيل العميل (أو العملاء) عندما يتم إيقاف تشغيل تطبيقك:
final CompletableFuture < Void > closeFuture = apnsClient . close ();
عند إيقاف التشغيل، سينتظر العملاء جميع الإشعارات المرسلة ولكن لم يتم استلامها لتلقي رد من الخادم. الإخطارات التي تم تمريرها إلى sendNotification
ولكن لم يتم إرسالها بعد إلى الخادم (أي الإخطارات المنتظرة في قائمة انتظار داخلية) ستفشل فورًا عند قطع الاتصال. يجب على المتصلين عمومًا التأكد من أن الخادم قد أقر بجميع الإشعارات المرسلة قبل إيقاف التشغيل.
إن تحقيق أقصى استفادة من موارد نظامك للتطبيقات عالية الإنتاجية يتطلب دائمًا بعض الجهد. لإرشادك خلال هذه العملية، قمنا بتجميع صفحة wiki تغطي بعض أفضل الممارسات لاستخدام Pushy. تمت تغطية كل هذه النقاط بمزيد من التفصيل على الويكي، ولكن بشكل عام، توصياتنا هي:
ApnsClient
كموارد طويلة الأمدCompletableFutures
إذا كنت تريد تتبع حالة إشعارات الدفع الخاصة بك يتضمن Pushy واجهة لمراقبة المقاييس التي توفر نظرة ثاقبة لسلوك العملاء وأدائهم. يمكنك كتابة التنفيذ الخاص بك لواجهة ApnsClientMetricsListener
لتسجيل المقاييس والإبلاغ عنها. نحن نوفر أيضًا مستمعي المقاييس الذين يقومون بجمع المقاييس والإبلاغ عنها باستخدام مكتبة Dropwizard Metrics واستخدام واجهة مراقبة تطبيق Micrometer كوحدات منفصلة. للبدء في تلقي المقاييس، قم بتعيين المستمع عند إنشاء عميل جديد:
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 ();
يرجى ملاحظة أن طرق التعامل مع المقاييس في تطبيق المستمع الخاص بك يجب ألا تستدعي كود الحظر مطلقًا. من المناسب زيادة العدادات مباشرة في أساليب المعالج، ولكن يجب إرسال الاستدعاءات إلى قواعد البيانات أو نقاط نهاية المراقبة عن بعد إلى سلاسل رسائل منفصلة.
إذا كنت بحاجة إلى استخدام وكيل للاتصالات الصادرة، فيمكنك تحديد ProxyHandlerFactory
عند إنشاء مثيل ApnsClient
الخاص بك. يتم توفير تطبيقات ملموسة لـ ProxyHandlerFactory
لوكلاء HTTP وSOCKS4 وSOCKS5.
مثال:
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 ();
إذا كنت تستخدم وكلاء HTTP الذين تم تكوينهم عبر خصائص نظام JVM، فيمكنك أيضًا استخدام:
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 SLF4J للتسجيل. إذا لم تكن على دراية به بالفعل، فإن SLF4J عبارة عن واجهة تسمح للمستخدمين باختيار مكتبة التسجيل التي سيتم استخدامها في وقت النشر عن طريق إضافة "ربط" محدد إلى مسار الفصل. لتجنب الاختيار نيابةً عنك، لا يعتمد Pushy نفسه على أي روابط SLF4J؛ ستحتاج إلى إضافة واحد بنفسك (إما عن طريق إضافته باعتباره تبعية في مشروعك الخاص أو عن طريق تثبيته مباشرة). إذا لم يكن لديك أي روابط SLF4J على مسار الفصل الخاص بك، فمن المحتمل أن ترى تحذيرًا يشبه هذا:
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.
لمزيد من المعلومات، راجع دليل المستخدم SLF4J.
يستخدم Pushy مستويات التسجيل على النحو التالي:
مستوى | تم تسجيل الأحداث |
---|---|
error | أخطاء جسيمة وغير قابلة للإصلاح؛ أخطاء قابلة للاسترداد والتي من المحتمل أن تشير إلى وجود خطأ في Pushy |
warn | أخطاء خطيرة، ولكن يمكن إصلاحها؛ الأخطاء التي قد تشير إلى وجود خطأ في رمز المتصل |
info | أحداث مهمة في دورة الحياة |
debug | أحداث دورة الحياة البسيطة؛ الاستثناءات المتوقعة |
trace | عمليات الإدخال والإخراج الفردية |
يشتمل Pushy على خادم APNs وهمي يمكن للمتصلين استخدامه في اختبارات التكامل والمعايير. ليس من الضروري استخدام خادم وهمي (أو أي فئات ذات صلة) في التشغيل العادي.
لإنشاء خادم وهمي، يجب على المتصلين استخدام MockApnsServerBuilder
. تتطلب جميع الخوادم PushNotificationHandler
(تم إنشاؤه بواسطة PushNotificationHandlerFactory
المقدم للمنشئ) الذي يقرر ما إذا كان الخادم الوهمي سيقبل أو يرفض كل إشعار دفع وارد. يشتمل Pushy على AcceptAllPushNotificationHandlerFactory
الذي يساعد في قياس الأداء و ValidatingPushNotificationHandlerFactory
الذي قد يكون مفيدًا لاختبار التكامل.
يمكن للمتصلين أيضًا توفير MockApnsServerListener
عند إنشاء خادم وهمي؛ يتم إخطار المستمعين عندما يقبل الخادم الوهمي أو يرفض إشعارًا من العميل.
انتهازي متاح بموجب ترخيص معهد ماساتشوستس للتكنولوجيا.
الإصدار الحالي من Pushy هو 0.15.4. إنها تعمل بكامل طاقتها وتستخدم على نطاق واسع في بيئات الإنتاج، ولكن واجهة برمجة التطبيقات العامة قد تتغير بشكل ملحوظ قبل إصدار 1.0.